1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * gld - Generic LAN Driver Version 2, PSARC/1997/382
  28  *
  29  * This is a utility module that provides generic facilities for
  30  * LAN  drivers.  The DLPI protocol and most STREAMS interfaces
  31  * are handled here.
  32  *
  33  * It no longer provides compatibility with drivers
  34  * implemented according to the GLD v0 documentation published
  35  * in 1993. (See PSARC 2003/728)
  36  */
  37 
  38 
  39 #include <sys/types.h>
  40 #include <sys/errno.h>
  41 #include <sys/stropts.h>
  42 #include <sys/stream.h>
  43 #include <sys/kmem.h>
  44 #include <sys/stat.h>
  45 #include <sys/modctl.h>
  46 #include <sys/kstat.h>
  47 #include <sys/debug.h>
  48 #include <sys/note.h>
  49 #include <sys/sysmacros.h>
  50 
  51 #include <sys/byteorder.h>
  52 #include <sys/strsun.h>
  53 #include <sys/strsubr.h>
  54 #include <sys/dlpi.h>
  55 #include <sys/pattr.h>
  56 #include <sys/ethernet.h>
  57 #include <sys/ib/clients/ibd/ibd.h>
  58 #include <sys/policy.h>
  59 #include <sys/atomic.h>
  60 
  61 #include <sys/multidata.h>
  62 #include <sys/gld.h>
  63 #include <sys/gldpriv.h>
  64 
  65 #include <sys/ddi.h>
  66 #include <sys/sunddi.h>
  67 
  68 /*
  69  * Macros to increment statistics.
  70  */
  71 
  72 /*
  73  * Increase kstats. Note this operation is not atomic. It can be used when
  74  * GLDM_LOCK_HELD_WRITE(macinfo).
  75  */
  76 #define BUMP(stats, vstats, stat, delta)        do {                    \
  77         ((stats)->stat) += (delta);                                  \
  78         _NOTE(CONSTANTCONDITION)                                        \
  79         if ((vstats) != NULL)                                           \
  80                 ((struct gld_stats *)(vstats))->stat += (delta);     \
  81         _NOTE(CONSTANTCONDITION)                                        \
  82 } while (0)
  83 
  84 #define ATOMIC_BUMP_STAT(stat, delta)   do {                    \
  85         _NOTE(CONSTANTCONDITION)                                \
  86         if (sizeof ((stat)) == sizeof (uint32_t)) {             \
  87                 atomic_add_32((uint32_t *)&(stat), (delta));        \
  88         _NOTE(CONSTANTCONDITION)                                \
  89         } else if (sizeof ((stat)) == sizeof (uint64_t)) {      \
  90                 atomic_add_64((uint64_t *)&(stat), (delta));        \
  91         }                                                       \
  92         _NOTE(CONSTANTCONDITION)                                \
  93 } while (0)
  94 
  95 #define ATOMIC_BUMP(stats, vstats, stat, delta) do {                    \
  96         ATOMIC_BUMP_STAT((stats)->stat, (delta));                    \
  97         _NOTE(CONSTANTCONDITION)                                        \
  98         if ((vstats) != NULL) {                                         \
  99                 ATOMIC_BUMP_STAT(((struct gld_stats *)(vstats))->stat,       \
 100                     (delta));                                           \
 101         }                                                               \
 102         _NOTE(CONSTANTCONDITION)                                        \
 103 } while (0)
 104 
 105 #define UPDATE_STATS(stats, vstats, pktinfo, delta) {                   \
 106         if ((pktinfo).isBroadcast) {                                    \
 107                 ATOMIC_BUMP((stats), (vstats),                          \
 108                     glds_brdcstxmt, (delta));                           \
 109         } else if ((pktinfo).isMulticast) {                             \
 110                 ATOMIC_BUMP((stats), (vstats), glds_multixmt, (delta)); \
 111         }                                                               \
 112         ATOMIC_BUMP((stats), (vstats), glds_bytexmt64,                  \
 113             ((pktinfo).pktLen));                                        \
 114         ATOMIC_BUMP((stats), (vstats), glds_pktxmt64, (delta));         \
 115 }
 116 
 117 #ifdef GLD_DEBUG
 118 int gld_debug = GLDERRS;
 119 #endif
 120 
 121 /* called from gld_register */
 122 static int gld_initstats(gld_mac_info_t *);
 123 
 124 /* called from kstat mechanism, and from wsrv's get_statistics */
 125 static int gld_update_kstat(kstat_t *, int);
 126 
 127 /* statistics for additional vlans */
 128 static int gld_init_vlan_stats(gld_vlan_t *);
 129 static int gld_update_vlan_kstat(kstat_t *, int);
 130 
 131 /* called from gld_getinfo */
 132 static dev_info_t *gld_finddevinfo(dev_t);
 133 
 134 /* called from wput, wsrv, unidata, and v0_sched to send a packet */
 135 /* also from the source routing stuff for sending RDE protocol packets */
 136 static int gld_start(queue_t *, mblk_t *, int, uint32_t);
 137 static int gld_start_mdt(queue_t *, mblk_t *, int);
 138 
 139 /* called from gld_start[_mdt] to loopback packet(s) in promiscuous mode */
 140 static void gld_precv(gld_mac_info_t *, mblk_t *, uint32_t, struct gld_stats *);
 141 static void gld_precv_mdt(gld_mac_info_t *, gld_vlan_t *, mblk_t *,
 142     pdesc_t *, pktinfo_t *);
 143 
 144 /* receive group: called from gld_recv and gld_precv* with maclock held */
 145 static void gld_sendup(gld_mac_info_t *, pktinfo_t *, mblk_t *,
 146     int (*)());
 147 static int gld_accept(gld_t *, pktinfo_t *);
 148 static int gld_mcmatch(gld_t *, pktinfo_t *);
 149 static int gld_multicast(unsigned char *, gld_t *);
 150 static int gld_paccept(gld_t *, pktinfo_t *);
 151 static void gld_passon(gld_t *, mblk_t *, pktinfo_t *,
 152     void (*)(queue_t *, mblk_t *));
 153 static mblk_t *gld_addudind(gld_t *, mblk_t *, pktinfo_t *, boolean_t);
 154 
 155 /* wsrv group: called from wsrv, single threaded per queue */
 156 static int gld_ioctl(queue_t *, mblk_t *);
 157 static void gld_fastpath(gld_t *, queue_t *, mblk_t *);
 158 static int gld_cmds(queue_t *, mblk_t *);
 159 static mblk_t *gld_bindack(queue_t *, mblk_t *);
 160 static int gld_notify_req(queue_t *, mblk_t *);
 161 static int gld_udqos(queue_t *, mblk_t *);
 162 static int gld_bind(queue_t *, mblk_t *);
 163 static int gld_unbind(queue_t *, mblk_t *);
 164 static int gld_inforeq(queue_t *, mblk_t *);
 165 static int gld_unitdata(queue_t *, mblk_t *);
 166 static int gldattach(queue_t *, mblk_t *);
 167 static int gldunattach(queue_t *, mblk_t *);
 168 static int gld_enable_multi(queue_t *, mblk_t *);
 169 static int gld_disable_multi(queue_t *, mblk_t *);
 170 static void gld_send_disable_multi(gld_mac_info_t *, gld_mcast_t *);
 171 static int gld_promisc(queue_t *, mblk_t *, t_uscalar_t, boolean_t);
 172 static int gld_physaddr(queue_t *, mblk_t *);
 173 static int gld_setaddr(queue_t *, mblk_t *);
 174 static int gld_get_statistics(queue_t *, mblk_t *);
 175 static int gld_cap(queue_t *, mblk_t *);
 176 static int gld_cap_ack(queue_t *, mblk_t *);
 177 static int gld_cap_enable(queue_t *, mblk_t *);
 178 
 179 /* misc utilities, some requiring various mutexes held */
 180 static int gld_start_mac(gld_mac_info_t *);
 181 static void gld_stop_mac(gld_mac_info_t *);
 182 static void gld_set_ipq(gld_t *);
 183 static void gld_flushqueue(queue_t *);
 184 static glddev_t *gld_devlookup(int);
 185 static int gld_findminor(glddev_t *);
 186 static void gldinsque(void *, void *);
 187 static void gldremque(void *);
 188 void gld_bitrevcopy(caddr_t, caddr_t, size_t);
 189 void gld_bitreverse(uchar_t *, size_t);
 190 char *gld_macaddr_sprintf(char *, unsigned char *, int);
 191 static gld_vlan_t *gld_add_vlan(gld_mac_info_t *, uint32_t vid);
 192 static void gld_rem_vlan(gld_vlan_t *);
 193 gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
 194 gld_vlan_t *gld_get_vlan(gld_mac_info_t *, uint32_t);
 195 
 196 #ifdef GLD_DEBUG
 197 static void gld_check_assertions(void);
 198 extern void gld_sr_dump(gld_mac_info_t *);
 199 #endif
 200 
 201 /*
 202  * Allocate and zero-out "number" structures each of type "structure" in
 203  * kernel memory.
 204  */
 205 #define GLD_GETSTRUCT(structure, number)   \
 206         (kmem_zalloc((uint_t)(sizeof (structure) * (number)), KM_NOSLEEP))
 207 
 208 #define abs(a) ((a) < 0 ? -(a) : a)
 209 
 210 uint32_t gld_global_options = GLD_OPT_NO_ETHRXSNAP;
 211 
 212 /*
 213  * The device is of DL_ETHER type and is able to support VLAN by itself.
 214  */
 215 #define VLAN_CAPABLE(macinfo) \
 216         ((macinfo)->gldm_type == DL_ETHER && \
 217         (macinfo)->gldm_send_tagged != NULL)
 218 
 219 /*
 220  * The set of notifications generatable by GLD itself, the additional
 221  * set that can be generated if the MAC driver provide the link-state
 222  * tracking callback capability, and the set supported by the GLD
 223  * notification code below.
 224  *
 225  * PLEASE keep these in sync with what the code actually does!
 226  */
 227 static const uint32_t gld_internal_notes =      DL_NOTE_PROMISC_ON_PHYS |
 228                                                 DL_NOTE_PROMISC_OFF_PHYS |
 229                                                 DL_NOTE_PHYS_ADDR;
 230 static const uint32_t gld_linkstate_notes =     DL_NOTE_LINK_DOWN |
 231                                                 DL_NOTE_LINK_UP |
 232                                                 DL_NOTE_SPEED;
 233 static const uint32_t gld_supported_notes =     DL_NOTE_PROMISC_ON_PHYS |
 234                                                 DL_NOTE_PROMISC_OFF_PHYS |
 235                                                 DL_NOTE_PHYS_ADDR |
 236                                                 DL_NOTE_LINK_DOWN |
 237                                                 DL_NOTE_LINK_UP |
 238                                                 DL_NOTE_SPEED;
 239 
 240 /* Media must correspond to #defines in gld.h */
 241 static char *gld_media[] = {
 242         "unknown",      /* GLDM_UNKNOWN - driver cannot determine media */
 243         "aui",          /* GLDM_AUI */
 244         "bnc",          /* GLDM_BNC */
 245         "twpair",       /* GLDM_TP */
 246         "fiber",        /* GLDM_FIBER */
 247         "100baseT",     /* GLDM_100BT */
 248         "100vgAnyLan",  /* GLDM_VGANYLAN */
 249         "10baseT",      /* GLDM_10BT */
 250         "ring4",        /* GLDM_RING4 */
 251         "ring16",       /* GLDM_RING16 */
 252         "PHY/MII",      /* GLDM_PHYMII */
 253         "100baseTX",    /* GLDM_100BTX */
 254         "100baseT4",    /* GLDM_100BT4 */
 255         "unknown",      /* skip */
 256         "ipib",         /* GLDM_IB */
 257 };
 258 
 259 /* Must correspond to #defines in gld.h */
 260 static char *gld_duplex[] = {
 261         "unknown",      /* GLD_DUPLEX_UNKNOWN - not known or not applicable */
 262         "half",         /* GLD_DUPLEX_HALF */
 263         "full"          /* GLD_DUPLEX_FULL */
 264 };
 265 
 266 /*
 267  * Interface types currently supported by GLD.
 268  * If you add new types, you must check all "XXX" strings in the GLD source
 269  * for implementation issues that may affect the support of your new type.
 270  * In particular, any type with gldm_addrlen > 6, or gldm_saplen != -2, will
 271  * require generalizing this GLD source to handle the new cases.  In other
 272  * words there are assumptions built into the code in a few places that must
 273  * be fixed.  Be sure to turn on DEBUG/ASSERT code when testing a new type.
 274  */
 275 static gld_interface_t interfaces[] = {
 276 
 277         /* Ethernet Bus */
 278         {
 279                 DL_ETHER,
 280                 (uint_t)-1,
 281                 sizeof (struct ether_header),
 282                 gld_interpret_ether,
 283                 NULL,
 284                 gld_fastpath_ether,
 285                 gld_unitdata_ether,
 286                 gld_init_ether,
 287                 gld_uninit_ether,
 288                 "ether"
 289         },
 290 
 291         /* Fiber Distributed data interface */
 292         {
 293                 DL_FDDI,
 294                 4352,
 295                 sizeof (struct fddi_mac_frm),
 296                 gld_interpret_fddi,
 297                 NULL,
 298                 gld_fastpath_fddi,
 299                 gld_unitdata_fddi,
 300                 gld_init_fddi,
 301                 gld_uninit_fddi,
 302                 "fddi"
 303         },
 304 
 305         /* Token Ring interface */
 306         {
 307                 DL_TPR,
 308                 17914,
 309                 -1,                     /* variable header size */
 310                 gld_interpret_tr,
 311                 NULL,
 312                 gld_fastpath_tr,
 313                 gld_unitdata_tr,
 314                 gld_init_tr,
 315                 gld_uninit_tr,
 316                 "tpr"
 317         },
 318 
 319         /* Infiniband */
 320         {
 321                 DL_IB,
 322                 4092,
 323                 sizeof (struct ipoib_header),
 324                 gld_interpret_ib,
 325                 gld_interpret_mdt_ib,
 326                 gld_fastpath_ib,
 327                 gld_unitdata_ib,
 328                 gld_init_ib,
 329                 gld_uninit_ib,
 330                 "ipib"
 331         },
 332 };
 333 
 334 /*
 335  * bit reversal lookup table.
 336  */
 337 static  uchar_t bit_rev[] = {
 338         0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
 339         0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
 340         0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
 341         0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
 342         0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
 343         0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
 344         0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
 345         0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
 346         0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
 347         0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
 348         0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
 349         0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
 350         0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
 351         0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
 352         0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
 353         0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
 354         0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
 355         0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
 356         0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
 357         0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
 358         0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
 359         0x3f, 0xbf, 0x7f, 0xff,
 360 };
 361 
 362 /*
 363  * User priorities, mapped from b_band.
 364  */
 365 static uint32_t user_priority[] = {
 366         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 367         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 368         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 369         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 370         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 371         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 372         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 373         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 374         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 375         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 376         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 377         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 378         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 379         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 380         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 381         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
 382 };
 383 
 384 #define UPRI(gld, band) ((band != 0) ? user_priority[(band)] : (gld)->gld_upri)
 385 
 386 static struct glddevice gld_device_list;  /* Per-system root of GLD tables */
 387 
 388 /*
 389  * Module linkage information for the kernel.
 390  */
 391 
 392 static struct modldrv modlmisc = {
 393         &mod_miscops,               /* Type of module - a utility provider */
 394         "Generic LAN Driver (" GLD_VERSION_STRING ")"
 395 #ifdef GLD_DEBUG
 396         " DEBUG"
 397 #endif
 398 };
 399 
 400 static struct modlinkage modlinkage = {
 401         MODREV_1, &modlmisc, NULL
 402 };
 403 
 404 int
 405 _init(void)
 406 {
 407         int e;
 408 
 409         /* initialize gld_device_list mutex */
 410         mutex_init(&gld_device_list.gld_devlock, NULL, MUTEX_DRIVER, NULL);
 411 
 412         /* initialize device driver (per-major) list */
 413         gld_device_list.gld_next =
 414             gld_device_list.gld_prev = &gld_device_list;
 415 
 416         if ((e = mod_install(&modlinkage)) != 0)
 417                 mutex_destroy(&gld_device_list.gld_devlock);
 418 
 419         return (e);
 420 }
 421 
 422 int
 423 _fini(void)
 424 {
 425         int e;
 426 
 427         if ((e = mod_remove(&modlinkage)) != 0)
 428                 return (e);
 429 
 430         ASSERT(gld_device_list.gld_next ==
 431             (glddev_t *)&gld_device_list.gld_next);
 432         ASSERT(gld_device_list.gld_prev ==
 433             (glddev_t *)&gld_device_list.gld_next);
 434         mutex_destroy(&gld_device_list.gld_devlock);
 435 
 436         return (e);
 437 }
 438 
 439 int
 440 _info(struct modinfo *modinfop)
 441 {
 442         return (mod_info(&modlinkage, modinfop));
 443 }
 444 
 445 /*
 446  * GLD service routines
 447  */
 448 
 449 /* So this gld binary maybe can be forward compatible with future v2 drivers */
 450 #define GLD_MAC_RESERVED (16 * sizeof (caddr_t))
 451 
 452 /*ARGSUSED*/
 453 gld_mac_info_t *
 454 gld_mac_alloc(dev_info_t *devinfo)
 455 {
 456         gld_mac_info_t *macinfo;
 457 
 458         macinfo = kmem_zalloc(sizeof (gld_mac_info_t) + GLD_MAC_RESERVED,
 459             KM_SLEEP);
 460 
 461         /*
 462          * The setting of gldm_driver_version will not be documented or allowed
 463          * until a future release.
 464          */
 465         macinfo->gldm_driver_version = GLD_VERSION_200;
 466 
 467         /*
 468          * GLD's version.  This also is undocumented for now, but will be
 469          * available if needed in the future.
 470          */
 471         macinfo->gldm_GLD_version = GLD_VERSION;
 472 
 473         return (macinfo);
 474 }
 475 
 476 /*
 477  * gld_mac_free must be called after the driver has removed interrupts
 478  * and completely stopped calling gld_recv() and gld_sched().  At that
 479  * point the interrupt routine is guaranteed by the system to have been
 480  * exited and the maclock is no longer needed.  Of course, it is
 481  * expected (required) that (assuming gld_register() succeeded),
 482  * gld_unregister() was called before gld_mac_free().
 483  */
 484 void
 485 gld_mac_free(gld_mac_info_t *macinfo)
 486 {
 487         ASSERT(macinfo);
 488         ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
 489 
 490         /*
 491          * Assert that if we made it through gld_register, then we must
 492          * have unregistered.
 493          */
 494         ASSERT(!GLDM_LOCK_INITED(macinfo) ||
 495             (macinfo->gldm_GLD_flags & GLD_UNREGISTERED));
 496 
 497         GLDM_LOCK_DESTROY(macinfo);
 498 
 499         kmem_free(macinfo, sizeof (gld_mac_info_t) + GLD_MAC_RESERVED);
 500 }
 501 
 502 /*
 503  * gld_register -- called once per device instance (PPA)
 504  *
 505  * During its attach routine, a real device driver will register with GLD
 506  * so that later opens and dl_attach_reqs will work.  The arguments are the
 507  * devinfo pointer, the device name, and a macinfo structure describing the
 508  * physical device instance.
 509  */
 510 int
 511 gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo)
 512 {
 513         int mediatype;
 514         int major = ddi_name_to_major(devname), i;
 515         glddev_t *glddev;
 516         gld_mac_pvt_t *mac_pvt;
 517         char minordev[32];
 518         char pbuf[3*GLD_MAX_ADDRLEN];
 519         gld_interface_t *ifp;
 520 
 521         ASSERT(devinfo != NULL);
 522         ASSERT(macinfo != NULL);
 523 
 524         if (macinfo->gldm_driver_version != GLD_VERSION)
 525                 return (DDI_FAILURE);
 526 
 527         mediatype = macinfo->gldm_type;
 528 
 529         /*
 530          * Entry points should be ready for us.
 531          * ioctl is optional.
 532          * set_multicast and get_stats are optional in v0.
 533          * intr is only required if you add an interrupt.
 534          */
 535         ASSERT(macinfo->gldm_reset != NULL);
 536         ASSERT(macinfo->gldm_start != NULL);
 537         ASSERT(macinfo->gldm_stop != NULL);
 538         ASSERT(macinfo->gldm_set_mac_addr != NULL);
 539         ASSERT(macinfo->gldm_set_promiscuous != NULL);
 540         ASSERT(macinfo->gldm_send != NULL);
 541 
 542         ASSERT(macinfo->gldm_maxpkt >= macinfo->gldm_minpkt);
 543         ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
 544         ASSERT(macinfo->gldm_broadcast_addr != NULL);
 545         ASSERT(macinfo->gldm_vendor_addr != NULL);
 546         ASSERT(macinfo->gldm_ident != NULL);
 547 
 548         if (macinfo->gldm_addrlen > GLD_MAX_ADDRLEN) {
 549                 cmn_err(CE_WARN, "GLD: %s driver gldm_addrlen %d > %d not sup"
 550                     "ported", devname, macinfo->gldm_addrlen, GLD_MAX_ADDRLEN);
 551                 return (DDI_FAILURE);
 552         }
 553 
 554         /*
 555          * GLD only functions properly with saplen == -2
 556          */
 557         if (macinfo->gldm_saplen != -2) {
 558                 cmn_err(CE_WARN, "GLD: %s driver gldm_saplen %d != -2 "
 559                     "not supported", devname, macinfo->gldm_saplen);
 560                 return (DDI_FAILURE);
 561         }
 562 
 563         /* see gld_rsrv() */
 564         if (ddi_getprop(DDI_DEV_T_NONE, devinfo, 0, "fast_recv", 0))
 565                 macinfo->gldm_options |= GLDOPT_FAST_RECV;
 566 
 567         mutex_enter(&gld_device_list.gld_devlock);
 568         glddev = gld_devlookup(major);
 569 
 570         /*
 571          *  Allocate per-driver (major) data structure if necessary
 572          */
 573         if (glddev == NULL) {
 574                 /* first occurrence of this device name (major number) */
 575                 glddev = GLD_GETSTRUCT(glddev_t, 1);
 576                 if (glddev == NULL) {
 577                         mutex_exit(&gld_device_list.gld_devlock);
 578                         return (DDI_FAILURE);
 579                 }
 580                 (void) strncpy(glddev->gld_name, devname,
 581                     sizeof (glddev->gld_name) - 1);
 582                 glddev->gld_major = major;
 583                 glddev->gld_nextminor = GLD_MIN_CLONE_MINOR;
 584                 glddev->gld_mac_next = glddev->gld_mac_prev =
 585                     (gld_mac_info_t *)&glddev->gld_mac_next;
 586                 glddev->gld_str_next = glddev->gld_str_prev =
 587                     (gld_t *)&glddev->gld_str_next;
 588                 mutex_init(&glddev->gld_devlock, NULL, MUTEX_DRIVER, NULL);
 589 
 590                 /* allow increase of number of supported multicast addrs */
 591                 glddev->gld_multisize = ddi_getprop(DDI_DEV_T_NONE,
 592                     devinfo, 0, "multisize", GLD_MAX_MULTICAST);
 593 
 594                 /*
 595                  * Optionally restrict DLPI provider style
 596                  *
 597                  * -1 - don't create style 1 nodes
 598                  * -2 - don't create style 2 nodes
 599                  */
 600                 glddev->gld_styles = ddi_getprop(DDI_DEV_T_NONE, devinfo, 0,
 601                     "gld-provider-styles", 0);
 602 
 603                 /* Stuff that's needed before any PPA gets attached */
 604                 glddev->gld_type = macinfo->gldm_type;
 605                 glddev->gld_minsdu = macinfo->gldm_minpkt;
 606                 glddev->gld_saplen = macinfo->gldm_saplen;
 607                 glddev->gld_addrlen = macinfo->gldm_addrlen;
 608                 glddev->gld_broadcast = kmem_zalloc(macinfo->gldm_addrlen,
 609                     KM_SLEEP);
 610                 bcopy(macinfo->gldm_broadcast_addr,
 611                     glddev->gld_broadcast, macinfo->gldm_addrlen);
 612                 glddev->gld_maxsdu = macinfo->gldm_maxpkt;
 613                 gldinsque(glddev, gld_device_list.gld_prev);
 614         }
 615         glddev->gld_ndevice++;
 616         /* Now glddev can't go away until we unregister this mac (or fail) */
 617         mutex_exit(&gld_device_list.gld_devlock);
 618 
 619         /*
 620          *  Per-instance initialization
 621          */
 622 
 623         /*
 624          * Initialize per-mac structure that is private to GLD.
 625          * Set up interface pointer. These are device class specific pointers
 626          * used to handle FDDI/TR/ETHER/IPoIB specific packets.
 627          */
 628         for (i = 0; i < sizeof (interfaces)/sizeof (*interfaces); i++) {
 629                 if (mediatype != interfaces[i].mac_type)
 630                         continue;
 631 
 632                 macinfo->gldm_mac_pvt = kmem_zalloc(sizeof (gld_mac_pvt_t),
 633                     KM_SLEEP);
 634                 ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep = ifp =
 635                     &interfaces[i];
 636                 break;
 637         }
 638 
 639         if (ifp == NULL) {
 640                 cmn_err(CE_WARN, "GLD: this version does not support %s driver "
 641                     "of type %d", devname, mediatype);
 642                 goto failure;
 643         }
 644 
 645         /*
 646          * Driver can only register MTU within legal media range.
 647          */
 648         if (macinfo->gldm_maxpkt > ifp->mtu_size) {
 649                 cmn_err(CE_WARN, "GLD: oversize MTU is specified by driver %s",
 650                     devname);
 651                 goto failure;
 652         }
 653 
 654         /*
 655          * Correct margin size if it is not set.
 656          */
 657         if (VLAN_CAPABLE(macinfo) && (macinfo->gldm_margin == 0))
 658                 macinfo->gldm_margin = VTAG_SIZE;
 659 
 660         /*
 661          * For now, only Infiniband drivers can use MDT. Do not add
 662          * support for Ethernet, FDDI or TR.
 663          */
 664         if (macinfo->gldm_mdt_pre != NULL) {
 665                 if (mediatype != DL_IB) {
 666                         cmn_err(CE_WARN, "GLD: MDT not supported for %s "
 667                             "driver of type %d", devname, mediatype);
 668                         goto failure;
 669                 }
 670 
 671                 /*
 672                  * Validate entry points.
 673                  */
 674                 if ((macinfo->gldm_mdt_send == NULL) ||
 675                     (macinfo->gldm_mdt_post == NULL)) {
 676                         cmn_err(CE_WARN, "GLD: invalid MDT entry points for "
 677                             "%s driver of type %d", devname, mediatype);
 678                         goto failure;
 679                 }
 680                 macinfo->gldm_options |= GLDOPT_MDT;
 681         }
 682 
 683         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
 684         mac_pvt->major_dev = glddev;
 685 
 686         mac_pvt->curr_macaddr = kmem_zalloc(macinfo->gldm_addrlen, KM_SLEEP);
 687         /*
 688          * XXX Do bit-reversed devices store gldm_vendor in canonical
 689          * format or in wire format?  Also gldm_broadcast.  For now
 690          * we are assuming canonical, but I'm not sure that makes the
 691          * most sense for ease of driver implementation.
 692          */
 693         bcopy(macinfo->gldm_vendor_addr, mac_pvt->curr_macaddr,
 694             macinfo->gldm_addrlen);
 695         mac_pvt->statistics = kmem_zalloc(sizeof (struct gld_stats), KM_SLEEP);
 696 
 697         /*
 698          * The available set of notifications is those generatable by GLD
 699          * itself, plus those corresponding to the capabilities of the MAC
 700          * driver, intersected with those supported by gld_notify_ind() above.
 701          */
 702         mac_pvt->notifications = gld_internal_notes;
 703         if (macinfo->gldm_capabilities & GLD_CAP_LINKSTATE)
 704                 mac_pvt->notifications |= gld_linkstate_notes;
 705         mac_pvt->notifications &= gld_supported_notes;
 706 
 707         GLDM_LOCK_INIT(macinfo);
 708 
 709         ddi_set_driver_private(devinfo, macinfo);
 710 
 711         /*
 712          * Now atomically get a PPA and put ourselves on the mac list.
 713          */
 714         mutex_enter(&glddev->gld_devlock);
 715 
 716 #ifdef DEBUG
 717         if (macinfo->gldm_ppa != ddi_get_instance(devinfo))
 718                 cmn_err(CE_WARN, "%s%d instance != ppa %d",
 719                     ddi_driver_name(devinfo), ddi_get_instance(devinfo),
 720                     macinfo->gldm_ppa);
 721 #endif
 722 
 723         /*
 724          * Create style 2 node (gated by gld-provider-styles property).
 725          *
 726          * NOTE: When the CLONE_DEV flag is specified to
 727          *       ddi_create_minor_node() the minor number argument is
 728          *       immaterial. Opens of that node will go via the clone
 729          *       driver and gld_open() will always be passed a dev_t with
 730          *       minor of zero.
 731          */
 732         if (glddev->gld_styles != -2) {
 733                 if (ddi_create_minor_node(devinfo, glddev->gld_name, S_IFCHR,
 734                     0, DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) {
 735                         mutex_exit(&glddev->gld_devlock);
 736                         goto late_failure;
 737                 }
 738         }
 739 
 740         /*
 741          * Create style 1 node (gated by gld-provider-styles property)
 742          */
 743         if (glddev->gld_styles != -1) {
 744                 (void) sprintf(minordev, "%s%d", glddev->gld_name,
 745                     macinfo->gldm_ppa);
 746                 if (ddi_create_minor_node(devinfo, minordev, S_IFCHR,
 747                     GLD_STYLE1_PPA_TO_MINOR(macinfo->gldm_ppa), DDI_NT_NET,
 748                     0) != DDI_SUCCESS) {
 749                         mutex_exit(&glddev->gld_devlock);
 750                         goto late_failure;
 751                 }
 752         }
 753 
 754         /* add ourselves to this major device's linked list of instances */
 755         gldinsque(macinfo, glddev->gld_mac_prev);
 756 
 757         mutex_exit(&glddev->gld_devlock);
 758 
 759         /*
 760          * Unfortunately we need the ppa before we call gld_initstats();
 761          * otherwise we would like to do this just above the mutex_enter
 762          * above.  In which case we could have set MAC_READY inside the
 763          * mutex and we wouldn't have needed to check it in open and
 764          * DL_ATTACH.  We wouldn't like to do the initstats/kstat_create
 765          * inside the mutex because it might get taken in our kstat_update
 766          * routine and cause a deadlock with kstat_chain_lock.
 767          */
 768 
 769         /* gld_initstats() calls (*ifp->init)() */
 770         if (gld_initstats(macinfo) != GLD_SUCCESS) {
 771                 mutex_enter(&glddev->gld_devlock);
 772                 gldremque(macinfo);
 773                 mutex_exit(&glddev->gld_devlock);
 774                 goto late_failure;
 775         }
 776 
 777         /*
 778          * Need to indicate we are NOW ready to process interrupts;
 779          * any interrupt before this is set is for someone else.
 780          * This flag is also now used to tell open, et. al. that this
 781          * mac is now fully ready and available for use.
 782          */
 783         GLDM_LOCK(macinfo, RW_WRITER);
 784         macinfo->gldm_GLD_flags |= GLD_MAC_READY;
 785         GLDM_UNLOCK(macinfo);
 786 
 787         /* log local ethernet address -- XXX not DDI compliant */
 788         if (macinfo->gldm_addrlen == sizeof (struct ether_addr))
 789                 (void) localetheraddr(
 790                     (struct ether_addr *)macinfo->gldm_vendor_addr, NULL);
 791 
 792         /* now put announcement into the message buffer */
 793         cmn_err(CE_CONT, "!%s%d: %s: type \"%s\" mac address %s\n",
 794             glddev->gld_name,
 795             macinfo->gldm_ppa, macinfo->gldm_ident,
 796             mac_pvt->interfacep->mac_string,
 797             gld_macaddr_sprintf(pbuf, macinfo->gldm_vendor_addr,
 798             macinfo->gldm_addrlen));
 799 
 800         ddi_report_dev(devinfo);
 801         return (DDI_SUCCESS);
 802 
 803 late_failure:
 804         ddi_remove_minor_node(devinfo, NULL);
 805         GLDM_LOCK_DESTROY(macinfo);
 806         if (mac_pvt->curr_macaddr != NULL)
 807                 kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
 808         if (mac_pvt->statistics != NULL)
 809                 kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
 810         kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
 811         macinfo->gldm_mac_pvt = NULL;
 812 
 813 failure:
 814         mutex_enter(&gld_device_list.gld_devlock);
 815         glddev->gld_ndevice--;
 816         /*
 817          * Note that just because this goes to zero here does not necessarily
 818          * mean that we were the one who added the glddev above.  It's
 819          * possible that the first mac unattached while were were in here
 820          * failing to attach the second mac.  But we're now the last.
 821          */
 822         if (glddev->gld_ndevice == 0) {
 823                 /* There should be no macinfos left */
 824                 ASSERT(glddev->gld_mac_next ==
 825                     (gld_mac_info_t *)&glddev->gld_mac_next);
 826                 ASSERT(glddev->gld_mac_prev ==
 827                     (gld_mac_info_t *)&glddev->gld_mac_next);
 828 
 829                 /*
 830                  * There should be no DL_UNATTACHED streams: the system
 831                  * should not have detached the "first" devinfo which has
 832                  * all the open style 2 streams.
 833                  *
 834                  * XXX This is not clear.  See gld_getinfo and Bug 1165519
 835                  */
 836                 ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
 837                 ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
 838 
 839                 gldremque(glddev);
 840                 mutex_destroy(&glddev->gld_devlock);
 841                 if (glddev->gld_broadcast != NULL)
 842                         kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
 843                 kmem_free(glddev, sizeof (glddev_t));
 844         }
 845         mutex_exit(&gld_device_list.gld_devlock);
 846 
 847         return (DDI_FAILURE);
 848 }
 849 
 850 /*
 851  * gld_unregister (macinfo)
 852  * remove the macinfo structure from local structures
 853  * this is cleanup for a driver to be unloaded
 854  */
 855 int
 856 gld_unregister(gld_mac_info_t *macinfo)
 857 {
 858         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
 859         glddev_t *glddev = mac_pvt->major_dev;
 860         gld_interface_t *ifp;
 861         int multisize = sizeof (gld_mcast_t) * glddev->gld_multisize;
 862 
 863         mutex_enter(&glddev->gld_devlock);
 864         GLDM_LOCK(macinfo, RW_WRITER);
 865 
 866         if (mac_pvt->nvlan > 0) {
 867                 GLDM_UNLOCK(macinfo);
 868                 mutex_exit(&glddev->gld_devlock);
 869                 return (DDI_FAILURE);
 870         }
 871 
 872 #ifdef  GLD_DEBUG
 873         {
 874                 int i;
 875 
 876                 for (i = 0; i < VLAN_HASHSZ; i++) {
 877                         if ((mac_pvt->vlan_hash[i] != NULL))
 878                                 cmn_err(CE_PANIC,
 879                                     "%s, line %d: "
 880                                     "mac_pvt->vlan_hash[%d] != NULL",
 881                                     __FILE__, __LINE__, i);
 882                 }
 883         }
 884 #endif
 885 
 886         /* Delete this mac */
 887         gldremque(macinfo);
 888 
 889         /* Disallow further entries to gld_recv() and gld_sched() */
 890         macinfo->gldm_GLD_flags |= GLD_UNREGISTERED;
 891 
 892         GLDM_UNLOCK(macinfo);
 893         mutex_exit(&glddev->gld_devlock);
 894 
 895         ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
 896         (*ifp->uninit)(macinfo);
 897 
 898         ASSERT(mac_pvt->kstatp);
 899         kstat_delete(mac_pvt->kstatp);
 900 
 901         ASSERT(GLDM_LOCK_INITED(macinfo));
 902         kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
 903         kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
 904 
 905         if (mac_pvt->mcast_table != NULL)
 906                 kmem_free(mac_pvt->mcast_table, multisize);
 907         kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
 908         macinfo->gldm_mac_pvt = (caddr_t)NULL;
 909 
 910         /* We now have one fewer instance for this major device */
 911         mutex_enter(&gld_device_list.gld_devlock);
 912         glddev->gld_ndevice--;
 913         if (glddev->gld_ndevice == 0) {
 914                 /* There should be no macinfos left */
 915                 ASSERT(glddev->gld_mac_next ==
 916                     (gld_mac_info_t *)&glddev->gld_mac_next);
 917                 ASSERT(glddev->gld_mac_prev ==
 918                     (gld_mac_info_t *)&glddev->gld_mac_next);
 919 
 920                 /*
 921                  * There should be no DL_UNATTACHED streams: the system
 922                  * should not have detached the "first" devinfo which has
 923                  * all the open style 2 streams.
 924                  *
 925                  * XXX This is not clear.  See gld_getinfo and Bug 1165519
 926                  */
 927                 ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
 928                 ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
 929 
 930                 ddi_remove_minor_node(macinfo->gldm_devinfo, NULL);
 931                 gldremque(glddev);
 932                 mutex_destroy(&glddev->gld_devlock);
 933                 if (glddev->gld_broadcast != NULL)
 934                         kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
 935                 kmem_free(glddev, sizeof (glddev_t));
 936         }
 937         mutex_exit(&gld_device_list.gld_devlock);
 938 
 939         return (DDI_SUCCESS);
 940 }
 941 
 942 /*
 943  * gld_initstats
 944  * called from gld_register
 945  */
 946 static int
 947 gld_initstats(gld_mac_info_t *macinfo)
 948 {
 949         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
 950         struct gldkstats *sp;
 951         glddev_t *glddev;
 952         kstat_t *ksp;
 953         gld_interface_t *ifp;
 954 
 955         glddev = mac_pvt->major_dev;
 956 
 957         if ((ksp = kstat_create(glddev->gld_name, macinfo->gldm_ppa,
 958             NULL, "net", KSTAT_TYPE_NAMED,
 959             sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) {
 960                 cmn_err(CE_WARN,
 961                     "GLD: failed to create kstat structure for %s%d",
 962                     glddev->gld_name, macinfo->gldm_ppa);
 963                 return (GLD_FAILURE);
 964         }
 965         mac_pvt->kstatp = ksp;
 966 
 967         ksp->ks_update = gld_update_kstat;
 968         ksp->ks_private = (void *)macinfo;
 969 
 970         sp = ksp->ks_data;
 971         kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32);
 972         kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32);
 973         kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG);
 974         kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG);
 975         kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32);
 976         kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32);
 977         kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG);
 978         kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG);
 979         kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG);
 980         kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG);
 981         kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG);
 982         kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG);
 983         kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG);
 984         kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG);
 985         kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG);
 986         kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64);
 987         kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64);
 988         kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64);
 989         kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64);
 990         kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG);
 991         kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64);
 992         kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR);
 993         kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR);
 994 
 995         kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG);
 996         kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG);
 997         kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG);
 998 
 999         kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp",
1000             KSTAT_DATA_UINT32);
1001         kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp",
1002             KSTAT_DATA_UINT32);
1003 
1004         ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
1005 
1006         (*ifp->init)(macinfo);
1007 
1008         kstat_install(ksp);
1009 
1010         return (GLD_SUCCESS);
1011 }
1012 
1013 /* called from kstat mechanism, and from wsrv's get_statistics_req */
1014 static int
1015 gld_update_kstat(kstat_t *ksp, int rw)
1016 {
1017         gld_mac_info_t  *macinfo;
1018         gld_mac_pvt_t   *mac_pvt;
1019         struct gldkstats *gsp;
1020         struct gld_stats *stats;
1021 
1022         if (rw == KSTAT_WRITE)
1023                 return (EACCES);
1024 
1025         macinfo = (gld_mac_info_t *)ksp->ks_private;
1026         ASSERT(macinfo != NULL);
1027 
1028         GLDM_LOCK(macinfo, RW_WRITER);
1029 
1030         if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) {
1031                 GLDM_UNLOCK(macinfo);
1032                 return (EIO);   /* this one's not ready yet */
1033         }
1034 
1035         if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
1036                 GLDM_UNLOCK(macinfo);
1037                 return (EIO);   /* this one's not ready any more */
1038         }
1039 
1040         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1041         gsp = mac_pvt->kstatp->ks_data;
1042         ASSERT(gsp);
1043         stats = mac_pvt->statistics;
1044 
1045         if (macinfo->gldm_get_stats)
1046                 (void) (*macinfo->gldm_get_stats)(macinfo, stats);
1047 
1048         gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff;
1049         gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff;
1050         gsp->glds_multixmt.value.ul = stats->glds_multixmt;
1051         gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt;
1052         gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf;       /* 0 for now */
1053         gsp->glds_xmtretry.value.ul = stats->glds_xmtretry;
1054 
1055         gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64;
1056         gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64;
1057         gsp->glds_xmtbadinterp.value.ui32 = stats->glds_xmtbadinterp;
1058 
1059         gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff;
1060         gsp->glds_errxmt.value.ul = stats->glds_errxmt;
1061         gsp->glds_errrcv.value.ul = stats->glds_errrcv;
1062         gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff;
1063         gsp->glds_multircv.value.ul = stats->glds_multircv;
1064         gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv;
1065         gsp->glds_blocked.value.ul = stats->glds_blocked;
1066         gsp->glds_overflow.value.ul = stats->glds_overflow;
1067         gsp->glds_underflow.value.ul = stats->glds_underflow;
1068         gsp->glds_missed.value.ul = stats->glds_missed;
1069         gsp->glds_norcvbuf.value.ul = stats->glds_norcvbuf +
1070             stats->glds_gldnorcvbuf;
1071         gsp->glds_intr.value.ul = stats->glds_intr;
1072 
1073         gsp->glds_speed.value.ui64 = stats->glds_speed;
1074         gsp->glds_unknowns.value.ul = stats->glds_unknowns;
1075         gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64;
1076         gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64;
1077         gsp->glds_rcvbadinterp.value.ui32 = stats->glds_rcvbadinterp;
1078 
1079         if (mac_pvt->nprom)
1080                 (void) strcpy(gsp->glds_prom.value.c, "phys");
1081         else if (mac_pvt->nprom_multi)
1082                 (void) strcpy(gsp->glds_prom.value.c, "multi");
1083         else
1084                 (void) strcpy(gsp->glds_prom.value.c, "off");
1085 
1086         (void) strcpy(gsp->glds_media.value.c, gld_media[
1087             stats->glds_media < sizeof (gld_media) / sizeof (gld_media[0])
1088             ? stats->glds_media : 0]);
1089 
1090         switch (macinfo->gldm_type) {
1091         case DL_ETHER:
1092                 gsp->glds_frame.value.ul = stats->glds_frame;
1093                 gsp->glds_crc.value.ul = stats->glds_crc;
1094                 gsp->glds_collisions.value.ul = stats->glds_collisions;
1095                 gsp->glds_excoll.value.ul = stats->glds_excoll;
1096                 gsp->glds_defer.value.ul = stats->glds_defer;
1097                 gsp->glds_short.value.ul = stats->glds_short;
1098                 gsp->glds_xmtlatecoll.value.ul = stats->glds_xmtlatecoll;
1099                 gsp->glds_nocarrier.value.ul = stats->glds_nocarrier;
1100                 gsp->glds_dot3_first_coll.value.ui32 =
1101                     stats->glds_dot3_first_coll;
1102                 gsp->glds_dot3_multi_coll.value.ui32 =
1103                     stats->glds_dot3_multi_coll;
1104                 gsp->glds_dot3_sqe_error.value.ui32 =
1105                     stats->glds_dot3_sqe_error;
1106                 gsp->glds_dot3_mac_xmt_error.value.ui32 =
1107                     stats->glds_dot3_mac_xmt_error;
1108                 gsp->glds_dot3_mac_rcv_error.value.ui32 =
1109                     stats->glds_dot3_mac_rcv_error;
1110                 gsp->glds_dot3_frame_too_long.value.ui32 =
1111                     stats->glds_dot3_frame_too_long;
1112                 (void) strcpy(gsp->glds_duplex.value.c, gld_duplex[
1113                     stats->glds_duplex <
1114                     sizeof (gld_duplex) / sizeof (gld_duplex[0]) ?
1115                     stats->glds_duplex : 0]);
1116                 break;
1117         case DL_TPR:
1118                 gsp->glds_dot5_line_error.value.ui32 =
1119                     stats->glds_dot5_line_error;
1120                 gsp->glds_dot5_burst_error.value.ui32 =
1121                     stats->glds_dot5_burst_error;
1122                 gsp->glds_dot5_signal_loss.value.ui32 =
1123                     stats->glds_dot5_signal_loss;
1124                 gsp->glds_dot5_ace_error.value.ui32 =
1125                     stats->glds_dot5_ace_error;
1126                 gsp->glds_dot5_internal_error.value.ui32 =
1127                     stats->glds_dot5_internal_error;
1128                 gsp->glds_dot5_lost_frame_error.value.ui32 =
1129                     stats->glds_dot5_lost_frame_error;
1130                 gsp->glds_dot5_frame_copied_error.value.ui32 =
1131                     stats->glds_dot5_frame_copied_error;
1132                 gsp->glds_dot5_token_error.value.ui32 =
1133                     stats->glds_dot5_token_error;
1134                 gsp->glds_dot5_freq_error.value.ui32 =
1135                     stats->glds_dot5_freq_error;
1136                 break;
1137         case DL_FDDI:
1138                 gsp->glds_fddi_mac_error.value.ui32 =
1139                     stats->glds_fddi_mac_error;
1140                 gsp->glds_fddi_mac_lost.value.ui32 =
1141                     stats->glds_fddi_mac_lost;
1142                 gsp->glds_fddi_mac_token.value.ui32 =
1143                     stats->glds_fddi_mac_token;
1144                 gsp->glds_fddi_mac_tvx_expired.value.ui32 =
1145                     stats->glds_fddi_mac_tvx_expired;
1146                 gsp->glds_fddi_mac_late.value.ui32 =
1147                     stats->glds_fddi_mac_late;
1148                 gsp->glds_fddi_mac_ring_op.value.ui32 =
1149                     stats->glds_fddi_mac_ring_op;
1150                 break;
1151         case DL_IB:
1152                 break;
1153         default:
1154                 break;
1155         }
1156 
1157         GLDM_UNLOCK(macinfo);
1158 
1159 #ifdef GLD_DEBUG
1160         gld_check_assertions();
1161         if (gld_debug & GLDRDE)
1162                 gld_sr_dump(macinfo);
1163 #endif
1164 
1165         return (0);
1166 }
1167 
1168 static int
1169 gld_init_vlan_stats(gld_vlan_t *vlan)
1170 {
1171         gld_mac_info_t *mac = vlan->gldv_mac;
1172         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
1173         struct gldkstats *sp;
1174         glddev_t *glddev;
1175         kstat_t *ksp;
1176         char *name;
1177         int instance;
1178 
1179         glddev = mac_pvt->major_dev;
1180         name = glddev->gld_name;
1181         instance = (vlan->gldv_id * GLD_VLAN_SCALE) + mac->gldm_ppa;
1182 
1183         if ((ksp = kstat_create(name, instance,
1184             NULL, "net", KSTAT_TYPE_NAMED,
1185             sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) {
1186                 cmn_err(CE_WARN,
1187                     "GLD: failed to create kstat structure for %s%d",
1188                     name, instance);
1189                 return (GLD_FAILURE);
1190         }
1191 
1192         vlan->gldv_kstatp = ksp;
1193 
1194         ksp->ks_update = gld_update_vlan_kstat;
1195         ksp->ks_private = (void *)vlan;
1196 
1197         sp = ksp->ks_data;
1198         kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32);
1199         kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32);
1200         kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG);
1201         kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG);
1202         kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32);
1203         kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32);
1204         kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG);
1205         kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG);
1206         kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG);
1207         kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG);
1208         kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG);
1209         kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG);
1210         kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG);
1211         kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG);
1212         kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG);
1213         kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64);
1214         kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64);
1215         kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64);
1216         kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64);
1217         kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG);
1218         kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64);
1219         kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR);
1220         kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR);
1221 
1222         kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG);
1223         kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG);
1224         kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG);
1225 
1226         kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp",
1227             KSTAT_DATA_UINT32);
1228         kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp",
1229             KSTAT_DATA_UINT32);
1230 
1231         kstat_install(ksp);
1232         return (GLD_SUCCESS);
1233 }
1234 
1235 static int
1236 gld_update_vlan_kstat(kstat_t *ksp, int rw)
1237 {
1238         gld_vlan_t      *vlan;
1239         gld_mac_info_t  *macinfo;
1240         struct gldkstats *gsp;
1241         struct gld_stats *stats;
1242         gld_mac_pvt_t *mac_pvt;
1243         uint32_t media;
1244 
1245         if (rw == KSTAT_WRITE)
1246                 return (EACCES);
1247 
1248         vlan = (gld_vlan_t *)ksp->ks_private;
1249         ASSERT(vlan != NULL);
1250 
1251         macinfo = vlan->gldv_mac;
1252         GLDM_LOCK(macinfo, RW_WRITER);
1253 
1254         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1255 
1256         gsp = vlan->gldv_kstatp->ks_data;
1257         ASSERT(gsp);
1258         stats = vlan->gldv_stats;
1259 
1260         gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff;
1261         gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff;
1262         gsp->glds_errxmt.value.ul = stats->glds_errxmt;
1263         gsp->glds_multixmt.value.ul = stats->glds_multixmt;
1264         gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt;
1265         gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf;
1266         gsp->glds_xmtretry.value.ul = stats->glds_xmtretry;
1267         gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64;
1268         gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64;
1269 
1270         gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff;
1271         gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff;
1272         gsp->glds_errrcv.value.ul = stats->glds_errrcv;
1273         gsp->glds_multircv.value.ul = stats->glds_multircv;
1274         gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv;
1275         gsp->glds_blocked.value.ul = stats->glds_blocked;
1276         gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64;
1277         gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64;
1278         gsp->glds_unknowns.value.ul = stats->glds_unknowns;
1279         gsp->glds_xmtbadinterp.value.ui32 = stats->glds_xmtbadinterp;
1280         gsp->glds_rcvbadinterp.value.ui32 = stats->glds_rcvbadinterp;
1281 
1282         gsp->glds_speed.value.ui64 = mac_pvt->statistics->glds_speed;
1283         media = mac_pvt->statistics->glds_media;
1284         (void) strcpy(gsp->glds_media.value.c,
1285             gld_media[media < sizeof (gld_media) / sizeof (gld_media[0]) ?
1286             media : 0]);
1287 
1288         GLDM_UNLOCK(macinfo);
1289         return (0);
1290 }
1291 
1292 /*
1293  * The device dependent driver specifies gld_getinfo as its getinfo routine.
1294  */
1295 /*ARGSUSED*/
1296 int
1297 gld_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1298 {
1299         dev_info_t      *devinfo;
1300         minor_t         minor = getminor((dev_t)arg);
1301         int             rc = DDI_FAILURE;
1302 
1303         switch (cmd) {
1304         case DDI_INFO_DEVT2DEVINFO:
1305                 if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) {
1306                         *(dev_info_t **)resultp = devinfo;
1307                         rc = DDI_SUCCESS;
1308                 }
1309                 break;
1310         case DDI_INFO_DEVT2INSTANCE:
1311                 /* Need static mapping for deferred attach */
1312                 if (minor == GLD_USE_STYLE2) {
1313                         /*
1314                          * Style 2:  this minor number does not correspond to
1315                          * any particular instance number.
1316                          */
1317                         rc = DDI_FAILURE;
1318                 } else if (minor <= GLD_MAX_STYLE1_MINOR) {
1319                         /* Style 1:  calculate the PPA from the minor */
1320                         *resultp = (void *)(uintptr_t)
1321                             GLD_STYLE1_MINOR_TO_PPA(minor);
1322                         rc = DDI_SUCCESS;
1323                 } else {
1324                         /* Clone:  look for it.  Not a static mapping */
1325                         if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) {
1326                                 *resultp = (void *)(uintptr_t)
1327                                     ddi_get_instance(devinfo);
1328                                 rc = DDI_SUCCESS;
1329                         }
1330                 }
1331                 break;
1332         }
1333 
1334         return (rc);
1335 }
1336 
1337 /* called from gld_getinfo */
1338 dev_info_t *
1339 gld_finddevinfo(dev_t dev)
1340 {
1341         minor_t         minor = getminor(dev);
1342         glddev_t        *device;
1343         gld_mac_info_t  *mac;
1344         gld_vlan_t      *vlan;
1345         gld_t           *str;
1346         dev_info_t      *devinfo = NULL;
1347         int             i;
1348 
1349         if (minor == GLD_USE_STYLE2) {
1350                 /*
1351                  * Style 2:  this minor number does not correspond to
1352                  * any particular instance number.
1353                  *
1354                  * XXX We don't know what to say.  See Bug 1165519.
1355                  */
1356                 return (NULL);
1357         }
1358 
1359         mutex_enter(&gld_device_list.gld_devlock);  /* hold the device */
1360 
1361         device = gld_devlookup(getmajor(dev));
1362         if (device == NULL) {
1363                 /* There are no attached instances of this device */
1364                 mutex_exit(&gld_device_list.gld_devlock);
1365                 return (NULL);
1366         }
1367 
1368         /*
1369          * Search all attached macs and streams.
1370          *
1371          * XXX We don't bother checking the DL_UNATTACHED streams since
1372          * we don't know what devinfo we should report back even if we
1373          * found the minor.  Maybe we should associate streams that are
1374          * not currently attached to a PPA with the "first" devinfo node
1375          * of the major device to attach -- the one that created the
1376          * minor node for the generic device.
1377          */
1378         mutex_enter(&device->gld_devlock);
1379 
1380         for (mac = device->gld_mac_next;
1381             mac != (gld_mac_info_t *)&device->gld_mac_next;
1382             mac = mac->gldm_next) {
1383                 gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
1384 
1385                 if (!(mac->gldm_GLD_flags & GLD_MAC_READY))
1386                         continue;       /* this one's not ready yet */
1387                 if (minor <= GLD_MAX_STYLE1_MINOR) {
1388                         /* Style 1 -- look for the corresponding PPA */
1389                         if (minor == GLD_STYLE1_PPA_TO_MINOR(mac->gldm_ppa)) {
1390                                 devinfo = mac->gldm_devinfo;
1391                                 goto out;       /* found it! */
1392                         } else
1393                                 continue;       /* not this PPA */
1394                 }
1395 
1396                 /* We are looking for a clone */
1397                 for (i = 0; i < VLAN_HASHSZ; i++) {
1398                         for (vlan = pvt->vlan_hash[i];
1399                             vlan != NULL; vlan = vlan->gldv_next) {
1400                                 for (str = vlan->gldv_str_next;
1401                                     str != (gld_t *)&vlan->gldv_str_next;
1402                                     str = str->gld_next) {
1403                                         ASSERT(str->gld_mac_info == mac);
1404                                         if (minor == str->gld_minor) {
1405                                                 devinfo = mac->gldm_devinfo;
1406                                                 goto out;
1407                                         }
1408                                 }
1409                         }
1410                 }
1411         }
1412 out:
1413         mutex_exit(&device->gld_devlock);
1414         mutex_exit(&gld_device_list.gld_devlock);
1415         return (devinfo);
1416 }
1417 
1418 /*
1419  * STREAMS open routine.  The device dependent driver specifies this as its
1420  * open entry point.
1421  */
1422 /*ARGSUSED2*/
1423 int
1424 gld_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
1425 {
1426         gld_mac_pvt_t *mac_pvt;
1427         gld_t *gld;
1428         glddev_t *glddev;
1429         gld_mac_info_t *macinfo;
1430         minor_t minor = getminor(*dev);
1431         gld_vlan_t *vlan;
1432         t_uscalar_t ppa;
1433 
1434         ASSERT(q != NULL);
1435 
1436         if (minor > GLD_MAX_STYLE1_MINOR)
1437                 return (ENXIO);
1438 
1439         ASSERT(q->q_ptr == NULL);    /* Clone device gives us a fresh Q */
1440 
1441         /* Find our per-major glddev_t structure */
1442         mutex_enter(&gld_device_list.gld_devlock);
1443         glddev = gld_devlookup(getmajor(*dev));
1444 
1445         /*
1446          * This glddev will hang around since detach (and therefore
1447          * gld_unregister) can't run while we're here in the open routine.
1448          */
1449         mutex_exit(&gld_device_list.gld_devlock);
1450 
1451         if (glddev == NULL)
1452                 return (ENXIO);
1453 
1454 #ifdef GLD_DEBUG
1455         if (gld_debug & GLDPROT) {
1456                 if (minor == GLD_USE_STYLE2)
1457                         cmn_err(CE_NOTE, "gld_open(%p, Style 2)", (void *)q);
1458                 else
1459                         cmn_err(CE_NOTE, "gld_open(%p, Style 1, minor = %d)",
1460                             (void *)q, minor);
1461         }
1462 #endif
1463 
1464         /*
1465          * get a per-stream structure and link things together so we
1466          * can easily find them later.
1467          */
1468         gld = kmem_zalloc(sizeof (gld_t), KM_SLEEP);
1469 
1470         /*
1471          * fill in the structure and state info
1472          */
1473         gld->gld_qptr = q;
1474         gld->gld_device = glddev;
1475         gld->gld_state = DL_UNATTACHED;
1476 
1477         /*
1478          * we must atomically find a free minor number and add the stream
1479          * to a list, because gld_findminor has to traverse the lists to
1480          * determine which minor numbers are free.
1481          */
1482         mutex_enter(&glddev->gld_devlock);
1483 
1484         /* find a free minor device number for the clone */
1485         gld->gld_minor = gld_findminor(glddev);
1486         if (gld->gld_minor == 0) {
1487                 mutex_exit(&glddev->gld_devlock);
1488                 kmem_free(gld, sizeof (gld_t));
1489                 return (ENOSR);
1490         }
1491 
1492 #ifdef GLD_VERBOSE_DEBUG
1493         if (gld_debug & GLDPROT)
1494                 cmn_err(CE_NOTE, "gld_open() gld ptr: %p minor: %d",
1495                     (void *)gld, gld->gld_minor);
1496 #endif
1497 
1498         if (minor == GLD_USE_STYLE2) {
1499                 gld->gld_style = DL_STYLE2;
1500                 *dev = makedevice(getmajor(*dev), gld->gld_minor);
1501                 WR(q)->q_ptr = q->q_ptr = (caddr_t)gld;
1502                 gldinsque(gld, glddev->gld_str_prev);
1503 #ifdef GLD_VERBOSE_DEBUG
1504                 if (gld_debug & GLDPROT)
1505                         cmn_err(CE_NOTE, "GLDstruct added to device list");
1506 #endif
1507                 (void) qassociate(q, -1);
1508                 goto done;
1509         }
1510 
1511         gld->gld_style = DL_STYLE1;
1512 
1513         /* the PPA is actually 1 less than the minordev */
1514         ppa = GLD_STYLE1_MINOR_TO_PPA(minor);
1515 
1516         for (macinfo = glddev->gld_mac_next;
1517             macinfo != (gld_mac_info_t *)(&glddev->gld_mac_next);
1518             macinfo = macinfo->gldm_next) {
1519                 ASSERT(macinfo != NULL);
1520                 if (macinfo->gldm_ppa != ppa)
1521                         continue;
1522 
1523                 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
1524                         continue;       /* this one's not ready yet */
1525 
1526                 /*
1527                  * we found the correct PPA
1528                  */
1529                 GLDM_LOCK(macinfo, RW_WRITER);
1530 
1531                 gld->gld_mac_info = macinfo;
1532 
1533                 if (macinfo->gldm_send_tagged != NULL)
1534                         gld->gld_send = macinfo->gldm_send_tagged;
1535                 else
1536                         gld->gld_send = macinfo->gldm_send;
1537 
1538                 /* now ready for action */
1539                 gld->gld_state = DL_UNBOUND;
1540 
1541                 if ((vlan = gld_get_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
1542                         GLDM_UNLOCK(macinfo);
1543                         mutex_exit(&glddev->gld_devlock);
1544                         kmem_free(gld, sizeof (gld_t));
1545                         return (EIO);
1546                 }
1547 
1548                 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1549                 if (!mac_pvt->started) {
1550                         if (gld_start_mac(macinfo) != GLD_SUCCESS) {
1551                                 gld_rem_vlan(vlan);
1552                                 GLDM_UNLOCK(macinfo);
1553                                 mutex_exit(&glddev->gld_devlock);
1554                                 kmem_free(gld, sizeof (gld_t));
1555                                 return (EIO);
1556                         }
1557                 }
1558 
1559                 gld->gld_vlan = vlan;
1560                 vlan->gldv_nstreams++;
1561                 gldinsque(gld, vlan->gldv_str_prev);
1562                 *dev = makedevice(getmajor(*dev), gld->gld_minor);
1563                 WR(q)->q_ptr = q->q_ptr = (caddr_t)gld;
1564 
1565                 GLDM_UNLOCK(macinfo);
1566 #ifdef GLD_VERBOSE_DEBUG
1567                 if (gld_debug & GLDPROT)
1568                         cmn_err(CE_NOTE,
1569                             "GLDstruct added to instance list");
1570 #endif
1571                 break;
1572         }
1573 
1574         if (gld->gld_state == DL_UNATTACHED) {
1575                 mutex_exit(&glddev->gld_devlock);
1576                 kmem_free(gld, sizeof (gld_t));
1577                 return (ENXIO);
1578         }
1579 
1580 done:
1581         mutex_exit(&glddev->gld_devlock);
1582         noenable(WR(q));        /* We'll do the qenables manually */
1583         qprocson(q);            /* start the queues running */
1584         qenable(WR(q));
1585         return (0);
1586 }
1587 
1588 /*
1589  * normal stream close call checks current status and cleans up
1590  * data structures that were dynamically allocated
1591  */
1592 /*ARGSUSED1*/
1593 int
1594 gld_close(queue_t *q, int flag, cred_t *cred)
1595 {
1596         gld_t   *gld = (gld_t *)q->q_ptr;
1597         glddev_t *glddev = gld->gld_device;
1598 
1599         ASSERT(q);
1600         ASSERT(gld);
1601 
1602 #ifdef GLD_DEBUG
1603         if (gld_debug & GLDPROT) {
1604                 cmn_err(CE_NOTE, "gld_close(%p, Style %d)",
1605                     (void *)q, (gld->gld_style & 0x1) + 1);
1606         }
1607 #endif
1608 
1609         /* Hold all device streams lists still while we check for a macinfo */
1610         mutex_enter(&glddev->gld_devlock);
1611 
1612         if (gld->gld_mac_info != NULL) {
1613                 /* If there's a macinfo, block recv while we change state */
1614                 GLDM_LOCK(gld->gld_mac_info, RW_WRITER);
1615                 gld->gld_flags |= GLD_STR_CLOSING; /* no more rcv putnexts */
1616                 GLDM_UNLOCK(gld->gld_mac_info);
1617         } else {
1618                 /* no mac DL_ATTACHED right now */
1619                 gld->gld_flags |= GLD_STR_CLOSING;
1620         }
1621 
1622         mutex_exit(&glddev->gld_devlock);
1623 
1624         /*
1625          * qprocsoff before we call gld_unbind/gldunattach, so that
1626          * we know wsrv isn't in there trying to undo what we're doing.
1627          */
1628         qprocsoff(q);
1629 
1630         ASSERT(gld->gld_wput_count == 0);
1631         gld->gld_wput_count = 0;     /* just in case */
1632 
1633         if (gld->gld_state == DL_IDLE) {
1634                 /* Need to unbind */
1635                 ASSERT(gld->gld_mac_info != NULL);
1636                 (void) gld_unbind(WR(q), NULL);
1637         }
1638 
1639         if (gld->gld_state == DL_UNBOUND) {
1640                 /*
1641                  * Need to unattach
1642                  * For style 2 stream, gldunattach also
1643                  * associate queue with NULL dip
1644                  */
1645                 ASSERT(gld->gld_mac_info != NULL);
1646                 (void) gldunattach(WR(q), NULL);
1647         }
1648 
1649         /* disassociate the stream from the device */
1650         q->q_ptr = WR(q)->q_ptr = NULL;
1651 
1652         /*
1653          * Since we unattached above (if necessary), we know that we're
1654          * on the per-major list of unattached streams, rather than a
1655          * per-PPA list.  So we know we should hold the devlock.
1656          */
1657         mutex_enter(&glddev->gld_devlock);
1658         gldremque(gld);                 /* remove from Style 2 list */
1659         mutex_exit(&glddev->gld_devlock);
1660 
1661         kmem_free(gld, sizeof (gld_t));
1662 
1663         return (0);
1664 }
1665 
1666 /*
1667  * gld_rsrv (q)
1668  *      simple read service procedure
1669  *      purpose is to avoid the time it takes for packets
1670  *      to move through IP so we can get them off the board
1671  *      as fast as possible due to limited PC resources.
1672  *
1673  *      This is not normally used in the current implementation.  It
1674  *      can be selected with the undocumented property "fast_recv".
1675  *      If that property is set, gld_recv will send the packet
1676  *      upstream with a putq() rather than a putnext(), thus causing
1677  *      this routine to be scheduled.
1678  */
1679 int
1680 gld_rsrv(queue_t *q)
1681 {
1682         mblk_t *mp;
1683 
1684         while ((mp = getq(q)) != NULL) {
1685                 if (canputnext(q)) {
1686                         putnext(q, mp);
1687                 } else {
1688                         freemsg(mp);
1689                 }
1690         }
1691         return (0);
1692 }
1693 
1694 /*
1695  * gld_wput (q, mp)
1696  * general gld stream write put routine. Receives fastpath data from upper
1697  * modules and processes it immediately.  ioctl and M_PROTO/M_PCPROTO are
1698  * queued for later processing by the service procedure.
1699  */
1700 
1701 int
1702 gld_wput(queue_t *q, mblk_t *mp)
1703 {
1704         gld_t  *gld = (gld_t *)(q->q_ptr);
1705         int     rc;
1706         boolean_t multidata = B_TRUE;
1707         uint32_t upri;
1708 
1709 #ifdef GLD_DEBUG
1710         if (gld_debug & GLDTRACE)
1711                 cmn_err(CE_NOTE, "gld_wput(%p %p): type %x",
1712                     (void *)q, (void *)mp, DB_TYPE(mp));
1713 #endif
1714         switch (DB_TYPE(mp)) {
1715 
1716         case M_DATA:
1717                 /* fast data / raw support */
1718                 /* we must be DL_ATTACHED and DL_BOUND to do this */
1719                 /* Tricky to access memory without taking the mutex */
1720                 if ((gld->gld_flags & (GLD_RAW | GLD_FAST)) == 0 ||
1721                     gld->gld_state != DL_IDLE) {
1722                         merror(q, mp, EPROTO);
1723                         break;
1724                 }
1725                 /*
1726                  * Cleanup MBLK_VTAG in case it is set by other
1727                  * modules. MBLK_VTAG is used to save the vtag information.
1728                  */
1729                 GLD_CLEAR_MBLK_VTAG(mp);
1730                 multidata = B_FALSE;
1731                 /* LINTED: E_CASE_FALLTHRU */
1732         case M_MULTIDATA:
1733                 /* Only call gld_start() directly if nothing queued ahead */
1734                 /* No guarantees about ordering with different threads */
1735                 if (q->q_first)
1736                         goto use_wsrv;
1737 
1738                 /*
1739                  * This can happen if wsrv has taken off the last mblk but
1740                  * is still processing it.
1741                  */
1742                 membar_consumer();
1743                 if (gld->gld_in_wsrv)
1744                         goto use_wsrv;
1745 
1746                 /*
1747                  * Keep a count of current wput calls to start.
1748                  * Nonzero count delays any attempted DL_UNBIND.
1749                  * See comments above gld_start().
1750                  */
1751                 atomic_inc_32((uint32_t *)&gld->gld_wput_count);
1752                 membar_enter();
1753 
1754                 /* Recheck state now wput_count is set to prevent DL_UNBIND */
1755                 /* If this Q is in process of DL_UNBIND, don't call start */
1756                 if (gld->gld_state != DL_IDLE || gld->gld_in_unbind) {
1757                         /* Extremely unlikely */
1758                         atomic_dec_32((uint32_t *)&gld->gld_wput_count);
1759                         goto use_wsrv;
1760                 }
1761 
1762                 /*
1763                  * Get the priority value. Note that in raw mode, the
1764                  * per-packet priority value kept in b_band is ignored.
1765                  */
1766                 upri = (gld->gld_flags & GLD_RAW) ? gld->gld_upri :
1767                     UPRI(gld, mp->b_band);
1768 
1769                 rc = (multidata) ? gld_start_mdt(q, mp, GLD_WPUT) :
1770                     gld_start(q, mp, GLD_WPUT, upri);
1771 
1772                 /* Allow DL_UNBIND again */
1773                 membar_exit();
1774                 atomic_dec_32((uint32_t *)&gld->gld_wput_count);
1775 
1776                 if (rc == GLD_NORESOURCES)
1777                         qenable(q);
1778                 break;  /*  Done with this packet */
1779 
1780 use_wsrv:
1781                 /* Q not empty, in DL_DETACH, or start gave NORESOURCES */
1782                 (void) putq(q, mp);
1783                 qenable(q);
1784                 break;
1785 
1786         case M_IOCTL:
1787                 /* ioctl relies on wsrv single threading per queue */
1788                 (void) putq(q, mp);
1789                 qenable(q);
1790                 break;
1791 
1792         case M_CTL:
1793                 (void) putq(q, mp);
1794                 qenable(q);
1795                 break;
1796 
1797         case M_FLUSH:           /* canonical flush handling */
1798                 /* XXX Should these be FLUSHALL? */
1799                 if (*mp->b_rptr & FLUSHW)
1800                         flushq(q, 0);
1801                 if (*mp->b_rptr & FLUSHR) {
1802                         flushq(RD(q), 0);
1803                         *mp->b_rptr &= ~FLUSHW;
1804                         qreply(q, mp);
1805                 } else
1806                         freemsg(mp);
1807                 break;
1808 
1809         case M_PROTO:
1810         case M_PCPROTO:
1811                 /* these rely on wsrv single threading per queue */
1812                 (void) putq(q, mp);
1813                 qenable(q);
1814                 break;
1815 
1816         default:
1817 #ifdef GLD_DEBUG
1818                 if (gld_debug & GLDETRACE)
1819                         cmn_err(CE_WARN,
1820                             "gld: Unexpected packet type from queue: 0x%x",
1821                             DB_TYPE(mp));
1822 #endif
1823                 freemsg(mp);
1824         }
1825         return (0);
1826 }
1827 
1828 /*
1829  * gld_wsrv - Incoming messages are processed according to the DLPI protocol
1830  * specification.
1831  *
1832  * wsrv is single-threaded per Q.  We make use of this to avoid taking the
1833  * lock for reading data items that are only ever written by us.
1834  */
1835 
1836 int
1837 gld_wsrv(queue_t *q)
1838 {
1839         mblk_t *mp;
1840         gld_t *gld = (gld_t *)q->q_ptr;
1841         gld_mac_info_t *macinfo;
1842         union DL_primitives *prim;
1843         int err;
1844         boolean_t multidata;
1845         uint32_t upri;
1846 
1847 #ifdef GLD_DEBUG
1848         if (gld_debug & GLDTRACE)
1849                 cmn_err(CE_NOTE, "gld_wsrv(%p)", (void *)q);
1850 #endif
1851 
1852         ASSERT(!gld->gld_in_wsrv);
1853 
1854         gld->gld_xwait = B_FALSE; /* We are now going to process this Q */
1855 
1856         if (q->q_first == NULL)
1857                 return (0);
1858 
1859         macinfo = gld->gld_mac_info;
1860 
1861         /*
1862          * Help wput avoid a call to gld_start if there might be a message
1863          * previously queued by that thread being processed here.
1864          */
1865         gld->gld_in_wsrv = B_TRUE;
1866         membar_enter();
1867 
1868         while ((mp = getq(q)) != NULL) {
1869                 switch (DB_TYPE(mp)) {
1870                 case M_DATA:
1871                 case M_MULTIDATA:
1872                         multidata = (DB_TYPE(mp) == M_MULTIDATA);
1873 
1874                         /*
1875                          * retry of a previously processed UNITDATA_REQ
1876                          * or is a RAW or FAST message from above.
1877                          */
1878                         if (macinfo == NULL) {
1879                                 /* No longer attached to a PPA, drop packet */
1880                                 freemsg(mp);
1881                                 break;
1882                         }
1883 
1884                         gld->gld_sched_ran = B_FALSE;
1885                         membar_enter();
1886 
1887                         /*
1888                          * Get the priority value. Note that in raw mode, the
1889                          * per-packet priority value kept in b_band is ignored.
1890                          */
1891                         upri = (gld->gld_flags & GLD_RAW) ? gld->gld_upri :
1892                             UPRI(gld, mp->b_band);
1893 
1894                         err = (multidata) ? gld_start_mdt(q, mp, GLD_WSRV) :
1895                             gld_start(q, mp, GLD_WSRV, upri);
1896                         if (err == GLD_NORESOURCES) {
1897                                 /* gld_sched will qenable us later */
1898                                 gld->gld_xwait = B_TRUE; /* want qenable */
1899                                 membar_enter();
1900                                 /*
1901                                  * v2:  we're not holding the lock; it's
1902                                  * possible that the driver could have already
1903                                  * called gld_sched (following up on its
1904                                  * return of GLD_NORESOURCES), before we got a
1905                                  * chance to do the putbq() and set gld_xwait.
1906                                  * So if we saw a call to gld_sched that
1907                                  * examined this queue, since our call to
1908                                  * gld_start() above, then it's possible we've
1909                                  * already seen the only call to gld_sched()
1910                                  * we're ever going to see.  So we better retry
1911                                  * transmitting this packet right now.
1912                                  */
1913                                 if (gld->gld_sched_ran) {
1914 #ifdef GLD_DEBUG
1915                                         if (gld_debug & GLDTRACE)
1916                                                 cmn_err(CE_NOTE, "gld_wsrv: "
1917                                                     "sched was called");
1918 #endif
1919                                         break;  /* try again right now */
1920                                 }
1921                                 gld->gld_in_wsrv = B_FALSE;
1922                                 return (0);
1923                         }
1924                         break;
1925 
1926                 case M_IOCTL:
1927                         (void) gld_ioctl(q, mp);
1928                         break;
1929 
1930                 case M_CTL:
1931                         if (macinfo == NULL) {
1932                                 freemsg(mp);
1933                                 break;
1934                         }
1935 
1936                         if (macinfo->gldm_mctl != NULL) {
1937                                 GLDM_LOCK(macinfo, RW_WRITER);
1938                                 (void) (*macinfo->gldm_mctl) (macinfo, q, mp);
1939                                 GLDM_UNLOCK(macinfo);
1940                         } else {
1941                                 /* This driver doesn't recognize, just drop */
1942                                 freemsg(mp);
1943                         }
1944                         break;
1945 
1946                 case M_PROTO:   /* Will be an DLPI message of some type */
1947                 case M_PCPROTO:
1948                         if ((err = gld_cmds(q, mp)) != GLDE_OK) {
1949                                 if (err == GLDE_RETRY) {
1950                                         gld->gld_in_wsrv = B_FALSE;
1951                                         return (0); /* quit while we're ahead */
1952                                 }
1953                                 prim = (union DL_primitives *)mp->b_rptr;
1954                                 dlerrorack(q, mp, prim->dl_primitive, err, 0);
1955                         }
1956                         break;
1957 
1958                 default:
1959                         /* This should never happen */
1960 #ifdef GLD_DEBUG
1961                         if (gld_debug & GLDERRS)
1962                                 cmn_err(CE_WARN,
1963                                     "gld_wsrv: db_type(%x) not supported",
1964                                     mp->b_datap->db_type);
1965 #endif
1966                         freemsg(mp);    /* unknown types are discarded */
1967                         break;
1968                 }
1969         }
1970 
1971         membar_exit();
1972         gld->gld_in_wsrv = B_FALSE;
1973         return (0);
1974 }
1975 
1976 /*
1977  * gld_start() can get called from gld_wput(), gld_wsrv(), or gld_unitdata().
1978  *
1979  * We only come directly from wput() in the GLD_FAST (fastpath) or RAW case.
1980  *
1981  * In particular, we must avoid calling gld_precv*() if we came from wput().
1982  * gld_precv*() is where we, on the transmit side, loop back our outgoing
1983  * packets to the receive side if we are in physical promiscuous mode.
1984  * Since the receive side holds a lock across its call to the upstream
1985  * putnext, and that upstream module could well have looped back to our
1986  * wput() routine on the same thread, we cannot call gld_precv* from here
1987  * for fear of causing a recursive lock entry in our receive code.
1988  *
1989  * There is a problem here when coming from gld_wput().  While wput
1990  * only comes here if the queue is attached to a PPA and bound to a SAP
1991  * and there are no messages on the queue ahead of the M_DATA that could
1992  * change that, it is theoretically possible that another thread could
1993  * now wput a DL_UNBIND and a DL_DETACH message, and the wsrv() routine
1994  * could wake up and process them, before we finish processing this
1995  * send of the M_DATA.  This can only possibly happen on a Style 2 RAW or
1996  * FAST (fastpath) stream:  non RAW/FAST streams always go through wsrv(),
1997  * and Style 1 streams only DL_DETACH in the close routine, where
1998  * qprocsoff() protects us.  If this happens we could end up calling
1999  * gldm_send() after we have detached the stream and possibly called
2000  * gldm_stop().  Worse, once the number of attached streams goes to zero,
2001  * detach/unregister could be called, and the macinfo could go away entirely.
2002  *
2003  * No one has ever seen this happen.
2004  *
2005  * It is some trouble to fix this, and we would rather not add any mutex
2006  * logic into the wput() routine, which is supposed to be a "fast"
2007  * path.
2008  *
2009  * What I've done is use an atomic counter to keep a count of the number
2010  * of threads currently calling gld_start() from wput() on this stream.
2011  * If DL_DETACH sees this as nonzero, it putbqs the request back onto
2012  * the queue and qenables, hoping to have better luck next time.  Since
2013  * people shouldn't be trying to send after they've asked to DL_DETACH,
2014  * hopefully very soon all the wput=>start threads should have returned
2015  * and the DL_DETACH will succeed.  It's hard to test this since the odds
2016  * of the failure even trying to happen are so small.  I probably could
2017  * have ignored the whole issue and never been the worse for it.
2018  *
2019  * Because some GLDv2 Ethernet drivers do not allow the size of transmitted
2020  * packet to be greater than ETHERMAX, we must first strip the VLAN tag
2021  * from a tagged packet before passing it to the driver's gld_send() entry
2022  * point function, and pass the VLAN tag as a separate argument. The
2023  * gld_send() function may fail. In that case, the packet will need to be
2024  * queued in order to be processed again in GLD's service routine. As the
2025  * VTAG has already been stripped at that time, we save the VTAG information
2026  * in (the unused fields of) dblk using GLD_SAVE_MBLK_VTAG(), so that the
2027  * VTAG can also be queued and be able to be got when gld_start() is called
2028  * next time from gld_wsrv().
2029  *
2030  * Some rules to use GLD_{CLEAR|SAVE}_MBLK_VTAG macros:
2031  *
2032  * - GLD_SAVE_MBLK_VTAG() must be called to save the VTAG information each time
2033  *   the message is queued by putbq().
2034  *
2035  * - GLD_CLEAR_MBLK_VTAG() must be called to clear the bogus VTAG information
2036  *   (if any) in dblk before the message is passed to the gld_start() function.
2037  */
2038 static int
2039 gld_start(queue_t *q, mblk_t *mp, int caller, uint32_t upri)
2040 {
2041         mblk_t *nmp;
2042         gld_t *gld = (gld_t *)q->q_ptr;
2043         gld_mac_info_t *macinfo;
2044         gld_mac_pvt_t *mac_pvt;
2045         int rc;
2046         gld_interface_t *ifp;
2047         pktinfo_t pktinfo;
2048         uint32_t vtag, vid;
2049         uint32_t raw_vtag = 0;
2050         gld_vlan_t *vlan;
2051         struct gld_stats *stats0, *stats = NULL;
2052 
2053         ASSERT(DB_TYPE(mp) == M_DATA);
2054         macinfo = gld->gld_mac_info;
2055         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2056         ifp = mac_pvt->interfacep;
2057         vlan = (gld_vlan_t *)gld->gld_vlan;
2058         vid = vlan->gldv_id;
2059 
2060         /*
2061          * If this interface is a VLAN, the kstats of corresponding
2062          * "VLAN 0" should also be updated. Note that the gld_vlan_t
2063          * structure for VLAN 0 might not exist if there are no DLPI
2064          * consumers attaching on VLAN 0. Fortunately we can directly
2065          * access VLAN 0's kstats from macinfo.
2066          *
2067          * Therefore, stats0 (VLAN 0's kstats) must always be
2068          * updated, and stats must to be updated if it is not NULL.
2069          */
2070         stats0 = mac_pvt->statistics;
2071         if (vid != VLAN_VID_NONE)
2072                 stats = vlan->gldv_stats;
2073 
2074         if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_TX) != 0) {
2075 #ifdef GLD_DEBUG
2076                 if (gld_debug & GLDERRS)
2077                         cmn_err(CE_WARN,
2078                             "gld_start: failed to interpret outbound packet");
2079 #endif
2080                 goto badarg;
2081         }
2082 
2083         vtag = VLAN_VID_NONE;
2084         raw_vtag = GLD_GET_MBLK_VTAG(mp);
2085         if (GLD_VTAG_TCI(raw_vtag) != 0) {
2086                 uint16_t raw_pri, raw_vid, evid;
2087 
2088                 /*
2089                  * Tagged packet.
2090                  */
2091                 raw_pri = GLD_VTAG_PRI(raw_vtag);
2092                 raw_vid = GLD_VTAG_VID(raw_vtag);
2093                 GLD_CLEAR_MBLK_VTAG(mp);
2094 
2095                 if (gld->gld_flags & GLD_RAW) {
2096                         /*
2097                          * In raw mode, we only expect untagged packets or
2098                          * special priority-tagged packets on a VLAN stream.
2099                          * Drop the packet if its VID is not zero.
2100                          */
2101                         if (vid != VLAN_VID_NONE && raw_vid != VLAN_VID_NONE)
2102                                 goto badarg;
2103 
2104                         /*
2105                          * If it is raw mode, use the per-stream priority if
2106                          * the priority is not specified in the packet.
2107                          * Otherwise, ignore the priority bits in the packet.
2108                          */
2109                         upri = (raw_pri != 0) ? raw_pri : upri;
2110                 }
2111 
2112                 if (vid == VLAN_VID_NONE && vid != raw_vid) {
2113                         gld_vlan_t *tmp_vlan;
2114 
2115                         /*
2116                          * This link is a physical link but the packet is
2117                          * a VLAN tagged packet, the kstats of corresponding
2118                          * VLAN (if any) should also be updated.
2119                          */
2120                         tmp_vlan = gld_find_vlan(macinfo, raw_vid);
2121                         if (tmp_vlan != NULL)
2122                                 stats = tmp_vlan->gldv_stats;
2123                 }
2124 
2125                 evid = (vid == VLAN_VID_NONE) ? raw_vid : vid;
2126                 if (evid != VLAN_VID_NONE || upri != 0)
2127                         vtag = GLD_MAKE_VTAG(upri, VLAN_CFI_ETHER, evid);
2128         } else {
2129                 /*
2130                  * Untagged packet:
2131                  * Get vtag from the attached PPA of this stream.
2132                  */
2133                 if ((vid != VLAN_VID_NONE) ||
2134                     ((macinfo->gldm_type == DL_ETHER) && (upri != 0))) {
2135                         vtag = GLD_MAKE_VTAG(upri, VLAN_CFI_ETHER, vid);
2136                 }
2137         }
2138 
2139         /*
2140          * We're not holding the lock for this check.  If the promiscuous
2141          * state is in flux it doesn't matter much if we get this wrong.
2142          */
2143         if (mac_pvt->nprom > 0) {
2144                 /*
2145                  * We want to loopback to the receive side, but to avoid
2146                  * recursive lock entry:  if we came from wput(), which
2147                  * could have looped back via IP from our own receive
2148                  * interrupt thread, we decline this request.  wput()
2149                  * will then queue the packet for wsrv().  This means
2150                  * that when snoop is running we don't get the advantage
2151                  * of the wput() multithreaded direct entry to the
2152                  * driver's send routine.
2153                  */
2154                 if (caller == GLD_WPUT) {
2155                         GLD_SAVE_MBLK_VTAG(mp, raw_vtag);
2156                         (void) putbq(q, mp);
2157                         return (GLD_NORESOURCES);
2158                 }
2159                 if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY)
2160                         nmp = dupmsg_noloan(mp);
2161                 else
2162                         nmp = dupmsg(mp);
2163         } else
2164                 nmp = NULL;             /* we need no loopback */
2165 
2166         if (ifp->hdr_size > 0 &&
2167             pktinfo.pktLen > ifp->hdr_size + (vtag == 0 ? 0 : VTAG_SIZE) +
2168             macinfo->gldm_maxpkt) {
2169                 if (nmp)
2170                         freemsg(nmp);   /* free the duped message */
2171 #ifdef GLD_DEBUG
2172                 if (gld_debug & GLDERRS)
2173                         cmn_err(CE_WARN,
2174                             "gld_start: oversize outbound packet, size %d,"
2175                             "max %d", pktinfo.pktLen,
2176                             ifp->hdr_size + (vtag == 0 ? 0 : VTAG_SIZE) +
2177                             macinfo->gldm_maxpkt);
2178 #endif
2179                 goto badarg;
2180         }
2181 
2182         rc = (*gld->gld_send)(macinfo, mp, vtag);
2183 
2184         if (rc != GLD_SUCCESS) {
2185                 if (rc == GLD_NORESOURCES) {
2186                         ATOMIC_BUMP(stats0, stats, glds_xmtretry, 1);
2187                         GLD_SAVE_MBLK_VTAG(mp, raw_vtag);
2188                         (void) putbq(q, mp);
2189                 } else {
2190                         /* transmit error; drop the packet */
2191                         freemsg(mp);
2192                         /* We're supposed to count failed attempts as well */
2193                         UPDATE_STATS(stats0, stats, pktinfo, 1);
2194 #ifdef GLD_DEBUG
2195                         if (gld_debug & GLDERRS)
2196                                 cmn_err(CE_WARN,
2197                                     "gld_start: gldm_send failed %d", rc);
2198 #endif
2199                 }
2200                 if (nmp)
2201                         freemsg(nmp);   /* free the dupped message */
2202                 return (rc);
2203         }
2204 
2205         UPDATE_STATS(stats0, stats, pktinfo, 1);
2206 
2207         /*
2208          * Loopback case. The message needs to be returned back on
2209          * the read side. This would silently fail if the dupmsg fails
2210          * above. This is probably OK, if there is no memory to dup the
2211          * block, then there isn't much we could do anyway.
2212          */
2213         if (nmp) {
2214                 GLDM_LOCK(macinfo, RW_WRITER);
2215                 gld_precv(macinfo, nmp, vtag, stats);
2216                 GLDM_UNLOCK(macinfo);
2217         }
2218 
2219         return (GLD_SUCCESS);
2220 badarg:
2221         freemsg(mp);
2222 
2223         ATOMIC_BUMP(stats0, stats, glds_xmtbadinterp, 1);
2224         return (GLD_BADARG);
2225 }
2226 
2227 /*
2228  * With MDT V.2 a single message mp can have one header area and multiple
2229  * payload areas. A packet is described by dl_pkt_info, and each packet can
2230  * span multiple payload areas (currently with TCP, each packet will have one
2231  * header and at the most two payload areas). MACs might have a limit on the
2232  * number of payload segments (i.e. per packet scatter-gather limit), and
2233  * MDT V.2 has a way of specifying that with mdt_span_limit; the MAC driver
2234  * might also have a limit on the total number of payloads in a message, and
2235  * that is specified by mdt_max_pld.
2236  */
2237 static int
2238 gld_start_mdt(queue_t *q, mblk_t *mp, int caller)
2239 {
2240         mblk_t *nextmp;
2241         gld_t *gld = (gld_t *)q->q_ptr;
2242         gld_mac_info_t *macinfo = gld->gld_mac_info;
2243         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2244         int numpacks, mdtpacks;
2245         gld_interface_t *ifp = mac_pvt->interfacep;
2246         pktinfo_t pktinfo;
2247         gld_vlan_t *vlan = (gld_vlan_t *)gld->gld_vlan;
2248         boolean_t doloop = B_FALSE;
2249         multidata_t *dlmdp;
2250         pdescinfo_t pinfo;
2251         pdesc_t *dl_pkt;
2252         void *cookie;
2253         uint_t totLen = 0;
2254 
2255         ASSERT(DB_TYPE(mp) == M_MULTIDATA);
2256 
2257         /*
2258          * We're not holding the lock for this check.  If the promiscuous
2259          * state is in flux it doesn't matter much if we get this wrong.
2260          */
2261         if (mac_pvt->nprom > 0) {
2262                 /*
2263                  * We want to loopback to the receive side, but to avoid
2264                  * recursive lock entry:  if we came from wput(), which
2265                  * could have looped back via IP from our own receive
2266                  * interrupt thread, we decline this request.  wput()
2267                  * will then queue the packet for wsrv().  This means
2268                  * that when snoop is running we don't get the advantage
2269                  * of the wput() multithreaded direct entry to the
2270                  * driver's send routine.
2271                  */
2272                 if (caller == GLD_WPUT) {
2273                         (void) putbq(q, mp);
2274                         return (GLD_NORESOURCES);
2275                 }
2276                 doloop = B_TRUE;
2277 
2278                 /*
2279                  * unlike the M_DATA case, we don't have to call
2280                  * dupmsg_noloan here because mmd_transform
2281                  * (called by gld_precv_mdt) will make a copy of
2282                  * each dblk.
2283                  */
2284         }
2285 
2286         while (mp != NULL) {
2287                 /*
2288                  * The lower layer driver only gets a single multidata
2289                  * message; this also makes it easier to handle noresources.
2290                  */
2291                 nextmp = mp->b_cont;
2292                 mp->b_cont = NULL;
2293 
2294                 /*
2295                  * Get number of packets in this message; if nothing
2296                  * to transmit, go to next message.
2297                  */
2298                 dlmdp = mmd_getmultidata(mp);
2299                 if ((mdtpacks = (int)mmd_getcnt(dlmdp, NULL, NULL)) == 0) {
2300                         freemsg(mp);
2301                         mp = nextmp;
2302                         continue;
2303                 }
2304 
2305                 /*
2306                  * Run interpreter to populate media specific pktinfo fields.
2307                  * This collects per MDT message information like sap,
2308                  * broad/multicast etc.
2309                  */
2310                 (void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, &pktinfo,
2311                     GLD_MDT_TX);
2312 
2313                 numpacks = (*macinfo->gldm_mdt_pre)(macinfo, mp, &cookie);
2314 
2315                 if (numpacks > 0) {
2316                         /*
2317                          * Driver indicates it can transmit at least 1, and
2318                          * possibly all, packets in MDT message.
2319                          */
2320                         int count = numpacks;
2321 
2322                         for (dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo);
2323                             (dl_pkt != NULL);
2324                             dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo)) {
2325                                 /*
2326                                  * Format this packet by adding link header and
2327                                  * adjusting pdescinfo to include it; get
2328                                  * packet length.
2329                                  */
2330                                 (void) (*ifp->interpreter_mdt)(macinfo, NULL,
2331                                     &pinfo, &pktinfo, GLD_MDT_TXPKT);
2332 
2333                                 totLen += pktinfo.pktLen;
2334 
2335                                 /*
2336                                  * Loop back packet before handing to the
2337                                  * driver.
2338                                  */
2339                                 if (doloop &&
2340                                     mmd_adjpdesc(dl_pkt, &pinfo) != NULL) {
2341                                         GLDM_LOCK(macinfo, RW_WRITER);
2342                                         gld_precv_mdt(macinfo, vlan, mp,
2343                                             dl_pkt, &pktinfo);
2344                                         GLDM_UNLOCK(macinfo);
2345                                 }
2346 
2347                                 /*
2348                                  * And send off to driver.
2349                                  */
2350                                 (*macinfo->gldm_mdt_send)(macinfo, cookie,
2351                                     &pinfo);
2352 
2353                                 /*
2354                                  * Be careful not to invoke getnextpdesc if we
2355                                  * already sent the last packet, since driver
2356                                  * might have posted it to hardware causing a
2357                                  * completion and freemsg() so the MDT data
2358                                  * structures might not be valid anymore.
2359                                  */
2360                                 if (--count == 0)
2361                                         break;
2362                         }
2363                         (*macinfo->gldm_mdt_post)(macinfo, mp, cookie);
2364                         pktinfo.pktLen = totLen;
2365                         UPDATE_STATS(vlan->gldv_stats, NULL, pktinfo, numpacks);
2366 
2367                         /*
2368                          * In the noresources case (when driver indicates it
2369                          * can not transmit all packets in the MDT message),
2370                          * adjust to skip the first few packets on retrial.
2371                          */
2372                         if (numpacks != mdtpacks) {
2373                                 /*
2374                                  * Release already processed packet descriptors.
2375                                  */
2376                                 for (count = 0; count < numpacks; count++) {
2377                                         dl_pkt = mmd_getfirstpdesc(dlmdp,
2378                                             &pinfo);
2379                                         mmd_rempdesc(dl_pkt);
2380                                 }
2381                                 ATOMIC_BUMP(vlan->gldv_stats, NULL,
2382                                     glds_xmtretry, 1);
2383                                 mp->b_cont = nextmp;
2384                                 (void) putbq(q, mp);
2385                                 return (GLD_NORESOURCES);
2386                         }
2387                 } else if (numpacks == 0) {
2388                         /*
2389                          * Driver indicates it can not transmit any packets
2390                          * currently and will request retrial later.
2391                          */
2392                         ATOMIC_BUMP(vlan->gldv_stats, NULL, glds_xmtretry, 1);
2393                         mp->b_cont = nextmp;
2394                         (void) putbq(q, mp);
2395                         return (GLD_NORESOURCES);
2396                 } else {
2397                         ASSERT(numpacks == -1);
2398                         /*
2399                          * We're supposed to count failed attempts as well.
2400                          */
2401                         dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo);
2402                         while (dl_pkt != NULL) {
2403                                 /*
2404                                  * Call interpreter to determine total packet
2405                                  * bytes that are being dropped.
2406                                  */
2407                                 (void) (*ifp->interpreter_mdt)(macinfo, NULL,
2408                                     &pinfo, &pktinfo, GLD_MDT_TXPKT);
2409 
2410                                 totLen += pktinfo.pktLen;
2411 
2412                                 dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo);
2413                         }
2414                         pktinfo.pktLen = totLen;
2415                         UPDATE_STATS(vlan->gldv_stats, NULL, pktinfo, mdtpacks);
2416 
2417                         /*
2418                          * Transmit error; drop the message, move on
2419                          * to the next one.
2420                          */
2421                         freemsg(mp);
2422                 }
2423 
2424                 /*
2425                  * Process the next multidata block, if there is one.
2426                  */
2427                 mp = nextmp;
2428         }
2429 
2430         return (GLD_SUCCESS);
2431 }
2432 
2433 /*
2434  * gld_intr (macinfo)
2435  */
2436 uint_t
2437 gld_intr(gld_mac_info_t *macinfo)
2438 {
2439         ASSERT(macinfo != NULL);
2440 
2441         if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
2442                 return (DDI_INTR_UNCLAIMED);
2443 
2444         return ((*macinfo->gldm_intr)(macinfo));
2445 }
2446 
2447 /*
2448  * gld_sched (macinfo)
2449  *
2450  * This routine scans the streams that refer to a specific macinfo
2451  * structure and causes the STREAMS scheduler to try to run them if
2452  * they are marked as waiting for the transmit buffer.
2453  */
2454 void
2455 gld_sched(gld_mac_info_t *macinfo)
2456 {
2457         gld_mac_pvt_t *mac_pvt;
2458         gld_t *gld;
2459         gld_vlan_t *vlan;
2460         int i;
2461 
2462         ASSERT(macinfo != NULL);
2463 
2464         GLDM_LOCK(macinfo, RW_WRITER);
2465 
2466         if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
2467                 /* We're probably being called from a leftover interrupt */
2468                 GLDM_UNLOCK(macinfo);
2469                 return;
2470         }
2471 
2472         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2473 
2474         for (i = 0; i < VLAN_HASHSZ; i++) {
2475                 for (vlan = mac_pvt->vlan_hash[i];
2476                     vlan != NULL; vlan = vlan->gldv_next) {
2477                         for (gld = vlan->gldv_str_next;
2478                             gld != (gld_t *)&vlan->gldv_str_next;
2479                             gld = gld->gld_next) {
2480                                 ASSERT(gld->gld_mac_info == macinfo);
2481                                 gld->gld_sched_ran = B_TRUE;
2482                                 membar_enter();
2483                                 if (gld->gld_xwait) {
2484                                         gld->gld_xwait = B_FALSE;
2485                                         qenable(WR(gld->gld_qptr));
2486                                 }
2487                         }
2488                 }
2489         }
2490 
2491         GLDM_UNLOCK(macinfo);
2492 }
2493 
2494 /*
2495  * gld_precv (macinfo, mp, vtag, stats)
2496  * called from gld_start to loopback a packet when in promiscuous mode
2497  *
2498  * VLAN 0's statistics need to be updated. If stats is not NULL,
2499  * it needs to be updated as well.
2500  */
2501 static void
2502 gld_precv(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag,
2503     struct gld_stats *stats)
2504 {
2505         gld_mac_pvt_t *mac_pvt;
2506         gld_interface_t *ifp;
2507         pktinfo_t pktinfo;
2508 
2509         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
2510 
2511         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2512         ifp = mac_pvt->interfacep;
2513 
2514         /*
2515          * call the media specific packet interpreter routine
2516          */
2517         if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RXLOOP) != 0) {
2518                 freemsg(mp);
2519                 BUMP(mac_pvt->statistics, stats, glds_rcvbadinterp, 1);
2520 #ifdef GLD_DEBUG
2521                 if (gld_debug & GLDERRS)
2522                         cmn_err(CE_WARN,
2523                             "gld_precv: interpreter failed");
2524 #endif
2525                 return;
2526         }
2527 
2528         /*
2529          * Update the vtag information.
2530          */
2531         pktinfo.isTagged = (vtag != VLAN_VID_NONE);
2532         pktinfo.vid = GLD_VTAG_VID(vtag);
2533         pktinfo.cfi = GLD_VTAG_CFI(vtag);
2534         pktinfo.user_pri = GLD_VTAG_PRI(vtag);
2535 
2536         gld_sendup(macinfo, &pktinfo, mp, gld_paccept);
2537 }
2538 
2539 /*
2540  * Called from gld_start_mdt to loopback packet(s) when in promiscuous mode.
2541  * Note that 'vlan' is always a physical link, because MDT can only be
2542  * enabled on non-VLAN streams.
2543  */
2544 /*ARGSUSED*/
2545 static void
2546 gld_precv_mdt(gld_mac_info_t *macinfo, gld_vlan_t *vlan, mblk_t *mp,
2547     pdesc_t *dl_pkt, pktinfo_t *pktinfo)
2548 {
2549         mblk_t *adjmp;
2550         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2551         gld_interface_t *ifp = mac_pvt->interfacep;
2552 
2553         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
2554 
2555         /*
2556          * Get source/destination.
2557          */
2558         (void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, pktinfo,
2559             GLD_MDT_RXLOOP);
2560         if ((adjmp = mmd_transform(dl_pkt)) != NULL)
2561                 gld_sendup(macinfo, pktinfo, adjmp, gld_paccept);
2562 }
2563 
2564 /*
2565  * gld_recv (macinfo, mp)
2566  * called with an mac-level packet in a mblock; take the maclock,
2567  * try the ip4q and ip6q hack, and otherwise call gld_sendup.
2568  *
2569  * V0 drivers already are holding the mutex when they call us.
2570  */
2571 void
2572 gld_recv(gld_mac_info_t *macinfo, mblk_t *mp)
2573 {
2574         gld_recv_tagged(macinfo, mp, VLAN_VTAG_NONE);
2575 }
2576 
2577 void
2578 gld_recv_tagged(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag)
2579 {
2580         gld_mac_pvt_t *mac_pvt;
2581         char pbuf[3*GLD_MAX_ADDRLEN];
2582         pktinfo_t pktinfo;
2583         gld_interface_t *ifp;
2584         queue_t *ipq = NULL;
2585         gld_vlan_t *vlan = NULL, *vlan0 = NULL, *vlann = NULL;
2586         struct gld_stats *stats0, *stats = NULL;
2587         uint32_t vid;
2588         int err;
2589 
2590         ASSERT(macinfo != NULL);
2591         ASSERT(mp->b_datap->db_ref);
2592 
2593         GLDM_LOCK(macinfo, RW_READER);
2594 
2595         if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
2596                 /* We're probably being called from a leftover interrupt */
2597                 freemsg(mp);
2598                 goto done;
2599         }
2600 
2601         /*
2602          * If this packet is a VLAN tagged packet, the kstats of corresponding
2603          * "VLAN 0" should also be updated. We can directly access VLAN 0's
2604          * kstats from macinfo.
2605          *
2606          * Further, the packets needs to be passed to VLAN 0 if there is
2607          * any DLPI consumer on VLAN 0 who is interested in tagged packets
2608          * (DL_PROMISC_SAP is on or is bounded to ETHERTYPE_VLAN SAP).
2609          */
2610         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2611         stats0 = mac_pvt->statistics;
2612 
2613         vid = GLD_VTAG_VID(vtag);
2614         vlan0 = gld_find_vlan(macinfo, VLAN_VID_NONE);
2615         if (vid != VLAN_VID_NONE) {
2616                 /*
2617                  * If there are no physical DLPI consumers interested in the
2618                  * VLAN packet, clear vlan0.
2619                  */
2620                 if ((vlan0 != NULL) && (vlan0->gldv_nvlan_sap == 0))
2621                         vlan0 = NULL;
2622                 /*
2623                  * vlann is the VLAN with the same VID as the VLAN packet.
2624                  */
2625                 vlann = gld_find_vlan(macinfo, vid);
2626                 if (vlann != NULL)
2627                         stats = vlann->gldv_stats;
2628         }
2629 
2630         vlan = (vid == VLAN_VID_NONE) ? vlan0 : vlann;
2631 
2632         ifp = mac_pvt->interfacep;
2633         err = (*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RXQUICK);
2634 
2635         BUMP(stats0, stats, glds_bytercv64, pktinfo.pktLen);
2636         BUMP(stats0, stats, glds_pktrcv64, 1);
2637 
2638         if ((vlann == NULL) && (vlan0 == NULL)) {
2639                 freemsg(mp);
2640                 goto done;
2641         }
2642 
2643         /*
2644          * Check whether underlying media code supports the IPQ hack:
2645          *
2646          * - the interpreter could quickly parse the packet
2647          * - the device type supports IPQ (ethernet and IPoIB)
2648          * - there is one, and only one, IP stream bound (to this VLAN)
2649          * - that stream is a "fastpath" stream
2650          * - the packet is of type ETHERTYPE_IP or ETHERTYPE_IPV6
2651          * - there are no streams in promiscuous mode (on this VLAN)
2652          * - if this packet is tagged, there is no need to send this
2653          *   packet to physical streams
2654          */
2655         if ((err != 0) && ((vlan != NULL) && (vlan->gldv_nprom == 0)) &&
2656             (vlan == vlan0 || vlan0 == NULL)) {
2657                 switch (pktinfo.ethertype) {
2658                 case ETHERTYPE_IP:
2659                         ipq = vlan->gldv_ipq;
2660                         break;
2661                 case ETHERTYPE_IPV6:
2662                         ipq = vlan->gldv_ipv6q;
2663                         break;
2664                 }
2665         }
2666 
2667         /*
2668          * Special case for IP; we can simply do the putnext here, if:
2669          * o The IPQ hack is possible (ipq != NULL).
2670          * o the packet is specifically for me, and therefore:
2671          * - the packet is not multicast or broadcast (fastpath only
2672          *   wants unicast packets).
2673          *
2674          * o the stream is not asserting flow control.
2675          */
2676         if (ipq != NULL &&
2677             pktinfo.isForMe &&
2678             canputnext(ipq)) {
2679                 /*
2680                  * Skip the mac header. We know there is no LLC1/SNAP header
2681                  * in this packet
2682                  */
2683                 mp->b_rptr += pktinfo.macLen;
2684                 putnext(ipq, mp);
2685                 goto done;
2686         }
2687 
2688         /*
2689          * call the media specific packet interpreter routine
2690          */
2691         if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RX) != 0) {
2692                 BUMP(stats0, stats, glds_rcvbadinterp, 1);
2693 #ifdef GLD_DEBUG
2694                 if (gld_debug & GLDERRS)
2695                         cmn_err(CE_WARN,
2696                             "gld_recv_tagged: interpreter failed");
2697 #endif
2698                 freemsg(mp);
2699                 goto done;
2700         }
2701 
2702         /*
2703          * This is safe even if vtag is VLAN_VTAG_NONE
2704          */
2705         pktinfo.vid = vid;
2706         pktinfo.cfi = GLD_VTAG_CFI(vtag);
2707 #ifdef GLD_DEBUG
2708         if (pktinfo.cfi != VLAN_CFI_ETHER)
2709                 cmn_err(CE_WARN, "gld_recv_tagged: non-ETHER CFI");
2710 #endif
2711         pktinfo.user_pri = GLD_VTAG_PRI(vtag);
2712         pktinfo.isTagged = (vtag != VLAN_VID_NONE);
2713 
2714 #ifdef GLD_DEBUG
2715         if ((gld_debug & GLDRECV) &&
2716             (!(gld_debug & GLDNOBR) ||
2717             (!pktinfo.isBroadcast && !pktinfo.isMulticast))) {
2718                 char pbuf2[3*GLD_MAX_ADDRLEN];
2719 
2720                 cmn_err(CE_CONT, "gld_recv_tagged: machdr=<%s -> %s>\n",
2721                     gld_macaddr_sprintf(pbuf, pktinfo.shost,
2722                     macinfo->gldm_addrlen), gld_macaddr_sprintf(pbuf2,
2723                     pktinfo.dhost, macinfo->gldm_addrlen));
2724                 cmn_err(CE_CONT, "gld_recv_tagged: VlanId %d UserPri %d\n",
2725                     pktinfo.vid,
2726                     pktinfo.user_pri);
2727                 cmn_err(CE_CONT, "gld_recv_tagged: ethertype: %4x Len: %4d "
2728                     "Hdr: %d,%d isMulticast: %s\n",
2729                     pktinfo.ethertype,
2730                     pktinfo.pktLen,
2731                     pktinfo.macLen,
2732                     pktinfo.hdrLen,
2733                     pktinfo.isMulticast ? "Y" : "N");
2734         }
2735 #endif
2736 
2737         gld_sendup(macinfo, &pktinfo, mp, gld_accept);
2738 
2739 done:
2740         GLDM_UNLOCK(macinfo);
2741 }
2742 
2743 /* =================================================================== */
2744 /* receive group: called from gld_recv and gld_precv* with maclock held */
2745 /* =================================================================== */
2746 
2747 /*
2748  * Search all the streams attached to the specified VLAN looking for
2749  * those eligible to receive the packet.
2750  * Note that in order to avoid an extra dupmsg(), if this is the first
2751  * eligible stream, remember it (in fgldp) so that we can send up the
2752  * message after this function.
2753  *
2754  * Return errno if fails. Currently the only error is ENOMEM.
2755  */
2756 static int
2757 gld_sendup_vlan(gld_vlan_t *vlan, pktinfo_t *pktinfo, mblk_t *mp,
2758     int (*acceptfunc)(), void (*send)(), int (*cansend)(), gld_t **fgldp)
2759 {
2760         mblk_t *nmp;
2761         gld_t *gld;
2762         int err = 0;
2763 
2764         ASSERT(vlan != NULL);
2765         for (gld = vlan->gldv_str_next; gld != (gld_t *)&vlan->gldv_str_next;
2766             gld = gld->gld_next) {
2767 #ifdef GLD_VERBOSE_DEBUG
2768                 cmn_err(CE_NOTE, "gld_sendup_vlan: SAP: %4x QPTR: %p "
2769                     "QSTATE: %s", gld->gld_sap, (void *)gld->gld_qptr,
2770                     gld->gld_state == DL_IDLE ? "IDLE" : "NOT IDLE");
2771 #endif
2772                 ASSERT(gld->gld_qptr != NULL);
2773                 ASSERT(gld->gld_state == DL_IDLE ||
2774                     gld->gld_state == DL_UNBOUND);
2775                 ASSERT(gld->gld_vlan == vlan);
2776 
2777                 if (gld->gld_state != DL_IDLE)
2778                         continue;       /* not eligible to receive */
2779                 if (gld->gld_flags & GLD_STR_CLOSING)
2780                         continue;       /* not eligible to receive */
2781 
2782 #ifdef GLD_DEBUG
2783                 if ((gld_debug & GLDRECV) &&
2784                     (!(gld_debug & GLDNOBR) ||
2785                     (!pktinfo->isBroadcast && !pktinfo->isMulticast)))
2786                         cmn_err(CE_NOTE,
2787                             "gld_sendup: queue sap: %4x promis: %s %s %s",
2788                             gld->gld_sap,
2789                             gld->gld_flags & GLD_PROM_PHYS ? "phys " : "     ",
2790                             gld->gld_flags & GLD_PROM_SAP  ? "sap  " : "     ",
2791                             gld->gld_flags & GLD_PROM_MULT ? "multi" : "     ");
2792 #endif
2793 
2794                 /*
2795                  * The accept function differs depending on whether this is
2796                  * a packet that we received from the wire or a loopback.
2797                  */
2798                 if ((*acceptfunc)(gld, pktinfo)) {
2799                         /* sap matches */
2800                         pktinfo->wasAccepted = 1; /* known protocol */
2801 
2802                         if (!(*cansend)(gld->gld_qptr)) {
2803                                 /*
2804                                  * Upper stream is not accepting messages, i.e.
2805                                  * it is flow controlled, therefore we will
2806                                  * forgo sending the message up this stream.
2807                                  */
2808 #ifdef GLD_DEBUG
2809                                 if (gld_debug & GLDETRACE)
2810                                         cmn_err(CE_WARN,
2811                                             "gld_sendup: canput failed");
2812 #endif
2813                                 BUMP(vlan->gldv_stats, NULL, glds_blocked, 1);
2814                                 qenable(gld->gld_qptr);
2815                                 continue;
2816                         }
2817 
2818                         /*
2819                          * In order to avoid an extra dupmsg(), remember this
2820                          * gld if this is the first eligible stream.
2821                          */
2822                         if (*fgldp == NULL) {
2823                                 *fgldp = gld;
2824                                 continue;
2825                         }
2826 
2827                         /* duplicate the packet for this stream */
2828                         nmp = dupmsg(mp);
2829                         if (nmp == NULL) {
2830                                 BUMP(vlan->gldv_stats, NULL,
2831                                     glds_gldnorcvbuf, 1);
2832 #ifdef GLD_DEBUG
2833                                 if (gld_debug & GLDERRS)
2834                                         cmn_err(CE_WARN,
2835                                             "gld_sendup: dupmsg failed");
2836 #endif
2837                                 /* couldn't get resources; drop it */
2838                                 err = ENOMEM;
2839                                 break;
2840                         }
2841                         /* pass the message up the stream */
2842                         gld_passon(gld, nmp, pktinfo, send);
2843                 }
2844         }
2845         return (err);
2846 }
2847 
2848 /*
2849  * gld_sendup (macinfo, pktinfo, mp, acceptfunc)
2850  * called with an ethernet packet in an mblk; must decide whether
2851  * packet is for us and which streams to queue it to.
2852  */
2853 static void
2854 gld_sendup(gld_mac_info_t *macinfo, pktinfo_t *pktinfo,
2855     mblk_t *mp, int (*acceptfunc)())
2856 {
2857         gld_t *fgld = NULL;
2858         void (*send)(queue_t *qp, mblk_t *mp);
2859         int (*cansend)(queue_t *qp);
2860         gld_vlan_t *vlan0, *vlann = NULL;
2861         struct gld_stats *stats0, *stats = NULL;
2862         int err = 0;
2863 
2864 #ifdef GLD_DEBUG
2865         if (gld_debug & GLDTRACE)
2866                 cmn_err(CE_NOTE, "gld_sendup(%p, %p)", (void *)mp,
2867                     (void *)macinfo);
2868 #endif
2869 
2870         ASSERT(mp != NULL);
2871         ASSERT(macinfo != NULL);
2872         ASSERT(pktinfo != NULL);
2873         ASSERT(GLDM_LOCK_HELD(macinfo));
2874 
2875         /*
2876          * The tagged packets should also be looped back (transmit-side)
2877          * or sent up (receive-side) to VLAN 0 if VLAN 0 is set to
2878          * DL_PROMISC_SAP or there is any DLPI consumer bind to the
2879          * ETHERTYPE_VLAN SAP. The kstats of VLAN 0 needs to be updated
2880          * as well.
2881          */
2882         stats0 = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->statistics;
2883         vlan0 = gld_find_vlan(macinfo, VLAN_VID_NONE);
2884         if (pktinfo->vid != VLAN_VID_NONE) {
2885                 if ((vlan0 != NULL) && (vlan0->gldv_nvlan_sap == 0))
2886                         vlan0 = NULL;
2887                 vlann = gld_find_vlan(macinfo, pktinfo->vid);
2888                 if (vlann != NULL)
2889                         stats = vlann->gldv_stats;
2890         }
2891 
2892         ASSERT((vlan0 != NULL) || (vlann != NULL));
2893 
2894         /*
2895          * The "fast" in "GLDOPT_FAST_RECV" refers to the speed at which
2896          * gld_recv returns to the caller's interrupt routine.  The total
2897          * network throughput would normally be lower when selecting this
2898          * option, because we putq the messages and process them later,
2899          * instead of sending them with putnext now.  Some time critical
2900          * device might need this, so it's here but undocumented.
2901          */
2902         if (macinfo->gldm_options & GLDOPT_FAST_RECV) {
2903                 send = (void (*)(queue_t *, mblk_t *))putq;
2904                 cansend = canput;
2905         } else {
2906                 send = (void (*)(queue_t *, mblk_t *))putnext;
2907                 cansend = canputnext;
2908         }
2909 
2910         /*
2911          * Send the packets for all eligible streams.
2912          */
2913         if (vlan0 != NULL) {
2914                 err = gld_sendup_vlan(vlan0, pktinfo, mp, acceptfunc, send,
2915                     cansend, &fgld);
2916         }
2917         if ((err == 0) && (vlann != NULL)) {
2918                 err = gld_sendup_vlan(vlann, pktinfo, mp, acceptfunc, send,
2919                     cansend, &fgld);
2920         }
2921 
2922         ASSERT(mp);
2923         /* send the original dup of the packet up the first stream found */
2924         if (fgld)
2925                 gld_passon(fgld, mp, pktinfo, send);
2926         else
2927                 freemsg(mp);    /* no streams matched */
2928 
2929         /* We do not count looped back packets */
2930         if (acceptfunc == gld_paccept)
2931                 return;         /* transmit loopback case */
2932 
2933         if (pktinfo->isBroadcast)
2934                 BUMP(stats0, stats, glds_brdcstrcv, 1);
2935         else if (pktinfo->isMulticast)
2936                 BUMP(stats0, stats, glds_multircv, 1);
2937 
2938         /* No stream accepted this packet */
2939         if (!pktinfo->wasAccepted)
2940                 BUMP(stats0, stats, glds_unknowns, 1);
2941 }
2942 
2943 #define GLD_IS_PHYS(gld)        \
2944         (((gld_vlan_t *)gld->gld_vlan)->gldv_id == VLAN_VID_NONE)
2945 
2946 /*
2947  * A packet matches a stream if:
2948  *      The stream's VLAN id is the same as the one in the packet.
2949  *  and the stream accepts EtherType encoded packets and the type matches
2950  *  or  the stream accepts LLC packets and the packet is an LLC packet
2951  */
2952 #define MATCH(stream, pktinfo) \
2953         ((((gld_vlan_t *)stream->gld_vlan)->gldv_id == pktinfo->vid) && \
2954         ((stream->gld_ethertype && stream->gld_sap == pktinfo->ethertype) || \
2955         (!stream->gld_ethertype && pktinfo->isLLC)))
2956 
2957 /*
2958  * This function validates a packet for sending up a particular
2959  * stream. The message header has been parsed and its characteristic
2960  * are recorded in the pktinfo data structure. The streams stack info
2961  * are presented in gld data structures.
2962  */
2963 static int
2964 gld_accept(gld_t *gld, pktinfo_t *pktinfo)
2965 {
2966         /*
2967          * if there is no match do not bother checking further.
2968          * Note that it is okay to examine gld_vlan because
2969          * macinfo->gldm_lock is held.
2970          *
2971          * Because all tagged packets have SAP value ETHERTYPE_VLAN,
2972          * these packets will pass the SAP filter check if the stream
2973          * is a ETHERTYPE_VLAN listener.
2974          */
2975         if ((!MATCH(gld, pktinfo) && !(gld->gld_flags & GLD_PROM_SAP) &&
2976             !(GLD_IS_PHYS(gld) && gld->gld_sap == ETHERTYPE_VLAN &&
2977             pktinfo->isTagged)))
2978                 return (0);
2979 
2980         /*
2981          * We don't accept any packet from the hardware if we originated it.
2982          * (Contrast gld_paccept, the send-loopback accept function.)
2983          */
2984         if (pktinfo->isLooped)
2985                 return (0);
2986 
2987         /*
2988          * If the packet is broadcast or sent to us directly we will accept it.
2989          * Also we will accept multicast packets requested by the stream.
2990          */
2991         if (pktinfo->isForMe || pktinfo->isBroadcast ||
2992             gld_mcmatch(gld, pktinfo))
2993                 return (1);
2994 
2995         /*
2996          * Finally, accept anything else if we're in promiscuous mode
2997          */
2998         if (gld->gld_flags & GLD_PROM_PHYS)
2999                 return (1);
3000 
3001         return (0);
3002 }
3003 
3004 /*
3005  * Return TRUE if the given multicast address is one
3006  * of those that this particular Stream is interested in.
3007  */
3008 static int
3009 gld_mcmatch(gld_t *gld, pktinfo_t *pktinfo)
3010 {
3011         /*
3012          * Return FALSE if not a multicast address.
3013          */
3014         if (!pktinfo->isMulticast)
3015                 return (0);
3016 
3017         /*
3018          * Check if all multicasts have been enabled for this Stream
3019          */
3020         if (gld->gld_flags & GLD_PROM_MULT)
3021                 return (1);
3022 
3023         /*
3024          * Return FALSE if no multicast addresses enabled for this Stream.
3025          */
3026         if (!gld->gld_mcast)
3027                 return (0);
3028 
3029         /*
3030          * Otherwise, look for it in the table.
3031          */
3032         return (gld_multicast(pktinfo->dhost, gld));
3033 }
3034 
3035 /*
3036  * gld_multicast determines if the address is a multicast address for
3037  * this stream.
3038  */
3039 static int
3040 gld_multicast(unsigned char *macaddr, gld_t *gld)
3041 {
3042         int i;
3043 
3044         ASSERT(GLDM_LOCK_HELD(gld->gld_mac_info));
3045 
3046         if (!gld->gld_mcast)
3047                 return (0);
3048 
3049         for (i = 0; i < gld->gld_multicnt; i++) {
3050                 if (gld->gld_mcast[i]) {
3051                         ASSERT(gld->gld_mcast[i]->gldm_refcnt);
3052                         if (mac_eq(gld->gld_mcast[i]->gldm_addr, macaddr,
3053                             gld->gld_mac_info->gldm_addrlen))
3054                                 return (1);
3055                 }
3056         }
3057 
3058         return (0);
3059 }
3060 
3061 /*
3062  * accept function for looped back packets
3063  */
3064 static int
3065 gld_paccept(gld_t *gld, pktinfo_t *pktinfo)
3066 {
3067         /*
3068          * Note that it is okay to examine gld_vlan because macinfo->gldm_lock
3069          * is held.
3070          *
3071          * If a stream is a ETHERTYPE_VLAN listener, it must
3072          * accept all tagged packets as those packets have SAP value
3073          * ETHERTYPE_VLAN.
3074          */
3075         return (gld->gld_flags & GLD_PROM_PHYS &&
3076             (MATCH(gld, pktinfo) || gld->gld_flags & GLD_PROM_SAP ||
3077             (GLD_IS_PHYS(gld) && gld->gld_sap == ETHERTYPE_VLAN &&
3078             pktinfo->isTagged)));
3079 
3080 }
3081 
3082 static void
3083 gld_passon(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo,
3084         void (*send)(queue_t *qp, mblk_t *mp))
3085 {
3086         boolean_t is_phys = GLD_IS_PHYS(gld);
3087         int skiplen;
3088         boolean_t addtag = B_FALSE;
3089         uint32_t vtag = 0;
3090 
3091 #ifdef GLD_DEBUG
3092         if (gld_debug & GLDTRACE)
3093                 cmn_err(CE_NOTE, "gld_passon(%p, %p, %p)", (void *)gld,
3094                     (void *)mp, (void *)pktinfo);
3095 
3096         if ((gld_debug & GLDRECV) && (!(gld_debug & GLDNOBR) ||
3097             (!pktinfo->isBroadcast && !pktinfo->isMulticast)))
3098                 cmn_err(CE_NOTE, "gld_passon: q: %p mblk: %p minor: %d sap: %x",
3099                     (void *)gld->gld_qptr->q_next, (void *)mp, gld->gld_minor,
3100                     gld->gld_sap);
3101 #endif
3102         /*
3103          * Figure out how much of the packet header to throw away.
3104          *
3105          * Normal DLPI (non RAW/FAST) streams also want the
3106          * DL_UNITDATA_IND M_PROTO message block prepended to the M_DATA.
3107          */
3108         if (gld->gld_flags & GLD_RAW) {
3109                 /*
3110                  * The packet will be tagged in the following cases:
3111                  *   - if priority is not 0
3112                  *   - a tagged packet sent on a physical link
3113                  */
3114                 if ((pktinfo->isTagged && is_phys) || (pktinfo->user_pri != 0))
3115                         addtag = B_TRUE;
3116                 skiplen = 0;
3117         } else {
3118                 /*
3119                  * The packet will be tagged if it meets all below conditions:
3120                  *   -  this is a physical stream
3121                  *   -  this packet is tagged packet
3122                  *   -  the stream is either a DL_PROMISC_SAP listener or a
3123                  *      ETHERTYPE_VLAN listener
3124                  */
3125                 if (is_phys && pktinfo->isTagged &&
3126                     ((gld->gld_sap == ETHERTYPE_VLAN) ||
3127                     (gld->gld_flags & GLD_PROM_SAP))) {
3128                         addtag = B_TRUE;
3129                 }
3130 
3131                 skiplen = pktinfo->macLen;           /* skip mac header */
3132                 if (gld->gld_ethertype)
3133                         skiplen += pktinfo->hdrLen;  /* skip any extra */
3134         }
3135         if (skiplen >= pktinfo->pktLen) {
3136                 /*
3137                  * If the interpreter did its job right, then it cannot be
3138                  * asking us to skip more bytes than are in the packet!
3139                  * However, there could be zero data bytes left after the
3140                  * amount to skip.  DLPI specifies that passed M_DATA blocks
3141                  * should contain at least one byte of data, so if we have
3142                  * none we just drop it.
3143                  */
3144                 ASSERT(!(skiplen > pktinfo->pktLen));
3145                 freemsg(mp);
3146                 return;
3147         }
3148 
3149         if (addtag) {
3150                 mblk_t *savemp = mp;
3151 
3152                 vtag = GLD_MAKE_VTAG(pktinfo->user_pri, pktinfo->cfi,
3153                     is_phys ? pktinfo->vid : VLAN_VID_NONE);
3154                 if ((mp = gld_insert_vtag_ether(mp, vtag)) == NULL) {
3155                         freemsg(savemp);
3156                         return;
3157                 }
3158         }
3159 
3160         /*
3161          * Skip over the header(s), taking care to possibly handle message
3162          * fragments shorter than the amount we need to skip.  Hopefully
3163          * the driver will put the entire packet, or at least the entire
3164          * header, into a single message block.  But we handle it if not.
3165          */
3166         while (skiplen >= MBLKL(mp)) {
3167                 mblk_t *savemp = mp;
3168                 skiplen -= MBLKL(mp);
3169                 mp = mp->b_cont;
3170                 ASSERT(mp != NULL);     /* because skiplen < pktinfo->pktLen */
3171                 freeb(savemp);
3172         }
3173         mp->b_rptr += skiplen;
3174 
3175         /* Add M_PROTO if necessary, and pass upstream */
3176         if (((gld->gld_flags & GLD_FAST) && !pktinfo->isMulticast &&
3177             !pktinfo->isBroadcast) || (gld->gld_flags & GLD_RAW)) {
3178                 /* RAW/FAST: just send up the M_DATA */
3179                 (*send)(gld->gld_qptr, mp);
3180         } else {
3181                 /* everybody else wants to see a unitdata_ind structure */
3182                 mp = gld_addudind(gld, mp, pktinfo, addtag);
3183                 if (mp)
3184                         (*send)(gld->gld_qptr, mp);
3185                 /* if it failed, gld_addudind already bumped statistic */
3186         }
3187 }
3188 
3189 /*
3190  * gld_addudind(gld, mp, pktinfo)
3191  * format a DL_UNITDATA_IND message to be sent upstream to the user
3192  */
3193 static mblk_t *
3194 gld_addudind(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo, boolean_t tagged)
3195 {
3196         gld_mac_info_t          *macinfo = gld->gld_mac_info;
3197         gld_vlan_t              *vlan = (gld_vlan_t *)gld->gld_vlan;
3198         dl_unitdata_ind_t       *dludindp;
3199         mblk_t                  *nmp;
3200         int                     size;
3201         int                     type;
3202 
3203 #ifdef GLD_DEBUG
3204         if (gld_debug & GLDTRACE)
3205                 cmn_err(CE_NOTE, "gld_addudind(%p, %p, %p)", (void *)gld,
3206                     (void *)mp, (void *)pktinfo);
3207 #endif
3208         ASSERT(macinfo != NULL);
3209 
3210         /*
3211          * Allocate the DL_UNITDATA_IND M_PROTO header, if allocation fails
3212          * might as well discard since we can't go further
3213          */
3214         size = sizeof (dl_unitdata_ind_t) +
3215             2 * (macinfo->gldm_addrlen + abs(macinfo->gldm_saplen));
3216         if ((nmp = allocb(size, BPRI_MED)) == NULL) {
3217                 freemsg(mp);
3218                 BUMP(vlan->gldv_stats, NULL, glds_gldnorcvbuf, 1);
3219 #ifdef GLD_DEBUG
3220                 if (gld_debug & GLDERRS)
3221                         cmn_err(CE_WARN,
3222                             "gld_addudind: allocb failed");
3223 #endif
3224                 return ((mblk_t *)NULL);
3225         }
3226         DB_TYPE(nmp) = M_PROTO;
3227         nmp->b_rptr = nmp->b_datap->db_lim - size;
3228 
3229         if (tagged)
3230                 type = ETHERTYPE_VLAN;
3231         else
3232                 type = (gld->gld_ethertype) ? pktinfo->ethertype : 0;
3233 
3234 
3235         /*
3236          * now setup the DL_UNITDATA_IND header
3237          *
3238          * XXX This looks broken if the saps aren't two bytes.
3239          */
3240         dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
3241         dludindp->dl_primitive = DL_UNITDATA_IND;
3242         dludindp->dl_src_addr_length =
3243             dludindp->dl_dest_addr_length = macinfo->gldm_addrlen +
3244             abs(macinfo->gldm_saplen);
3245         dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
3246         dludindp->dl_src_addr_offset = dludindp->dl_dest_addr_offset +
3247             dludindp->dl_dest_addr_length;
3248 
3249         dludindp->dl_group_address = (pktinfo->isMulticast ||
3250             pktinfo->isBroadcast);
3251 
3252         nmp->b_wptr = nmp->b_rptr + dludindp->dl_dest_addr_offset;
3253 
3254         mac_copy(pktinfo->dhost, nmp->b_wptr, macinfo->gldm_addrlen);
3255         nmp->b_wptr += macinfo->gldm_addrlen;
3256 
3257         ASSERT(macinfo->gldm_saplen == -2);  /* XXX following code assumes */
3258         *(ushort_t *)(nmp->b_wptr) = type;
3259         nmp->b_wptr += abs(macinfo->gldm_saplen);
3260 
3261         ASSERT(nmp->b_wptr == nmp->b_rptr + dludindp->dl_src_addr_offset);
3262 
3263         mac_copy(pktinfo->shost, nmp->b_wptr, macinfo->gldm_addrlen);
3264         nmp->b_wptr += macinfo->gldm_addrlen;
3265 
3266         *(ushort_t *)(nmp->b_wptr) = type;
3267         nmp->b_wptr += abs(macinfo->gldm_saplen);
3268 
3269         if (pktinfo->nosource)
3270                 dludindp->dl_src_addr_offset = dludindp->dl_src_addr_length = 0;
3271         linkb(nmp, mp);
3272         return (nmp);
3273 }
3274 
3275 /* ======================================================= */
3276 /* wsrv group: called from wsrv, single threaded per queue */
3277 /* ======================================================= */
3278 
3279 /*
3280  * We go to some trouble to avoid taking the same lock during normal
3281  * transmit processing as we do during normal receive processing.
3282  *
3283  * Elements of the per-instance macinfo and per-stream gld_t structures
3284  * are for the most part protected by the GLDM_LOCK rwlock/mutex.
3285  * (Elements of the gld_mac_pvt_t structure are considered part of the
3286  * macinfo structure for purposes of this discussion).
3287  *
3288  * However, it is more complicated than that:
3289  *
3290  *      Elements of the macinfo structure that are set before the macinfo
3291  *      structure is added to its device list by gld_register(), and never
3292  *      thereafter modified, are accessed without requiring taking the lock.
3293  *      A similar rule applies to those elements of the gld_t structure that
3294  *      are written by gld_open() before the stream is added to any list.
3295  *
3296  *      Most other elements of the macinfo structure may only be read or
3297  *      written while holding the maclock.
3298  *
3299  *      Most writable elements of the gld_t structure are written only
3300  *      within the single-threaded domain of wsrv() and subsidiaries.
3301  *      (This domain includes open/close while qprocs are not on.)
3302  *      The maclock need not be taken while within that domain
3303  *      simply to read those elements.  Writing to them, even within
3304  *      that domain, or reading from it outside that domain, requires
3305  *      holding the maclock.  Exception:  if the stream is not
3306  *      presently attached to a PPA, there is no associated macinfo,
3307  *      and no maclock need be taken.
3308  *
3309  *      The curr_macaddr element of the mac private structure is also
3310  *      protected by the GLDM_LOCK rwlock/mutex, like most other members
3311  *      of that structure. However, there are a few instances in the
3312  *      transmit path where we choose to forgo lock protection when
3313  *      reading this variable. This is to avoid lock contention between
3314  *      threads executing the DL_UNITDATA_REQ case and receive threads.
3315  *      In doing so we will take a small risk or a few corrupted packets
3316  *      during the short an rare times when someone is changing the interface's
3317  *      physical address. We consider the small cost in this rare case to be
3318  *      worth the benefit of reduced lock contention under normal operating
3319  *      conditions. The risk/cost is small because:
3320  *          1. there is no guarantee at this layer of uncorrupted delivery.
3321  *          2. the physaddr doesn't change very often - no performance hit.
3322  *          3. if the physaddr changes, other stuff is going to be screwed
3323  *             up for a while anyway, while other sites refigure ARP, etc.,
3324  *             so losing a couple of packets is the least of our worries.
3325  *
3326  *      The list of streams associated with a macinfo is protected by
3327  *      two locks:  the per-macinfo maclock, and the per-major-device
3328  *      gld_devlock.  Both must be held to modify the list, but either
3329  *      may be held to protect the list during reading/traversing.  This
3330  *      allows independent locking for multiple instances in the receive
3331  *      path (using macinfo), while facilitating routines that must search
3332  *      the entire set of streams associated with a major device, such as
3333  *      gld_findminor(), gld_finddevinfo(), close().  The "nstreams"
3334  *      macinfo element, and the gld_mac_info gld_t element, are similarly
3335  *      protected, since they change at exactly the same time macinfo
3336  *      streams list does.
3337  *
3338  *      The list of macinfo structures associated with a major device
3339  *      structure is protected by the gld_devlock, as is the per-major
3340  *      list of Style 2 streams in the DL_UNATTACHED state.
3341  *
3342  *      The list of major devices is kept on a module-global list
3343  *      gld_device_list, which has its own lock to protect the list.
3344  *
3345  *      When it is necessary to hold more than one lock at a time, they
3346  *      are acquired in this "outside in" order:
3347  *              gld_device_list.gld_devlock
3348  *              glddev->gld_devlock
3349  *              GLDM_LOCK(macinfo)
3350  *
3351  *      Finally, there are some "volatile" elements of the gld_t structure
3352  *      used for synchronization between various routines that don't share
3353  *      the same mutexes.  See the routines for details.  These are:
3354  *              gld_xwait       between gld_wsrv() and gld_sched()
3355  *              gld_sched_ran   between gld_wsrv() and gld_sched()
3356  *              gld_in_unbind   between gld_wput() and wsrv's gld_unbind()
3357  *              gld_wput_count  between gld_wput() and wsrv's gld_unbind()
3358  *              gld_in_wsrv     between gld_wput() and gld_wsrv()
3359  *                              (used in conjunction with q->q_first)
3360  */
3361 
3362 /*
3363  * gld_ioctl (q, mp)
3364  * handles all ioctl requests passed downstream. This routine is
3365  * passed a pointer to the message block with the ioctl request in it, and a
3366  * pointer to the queue so it can respond to the ioctl request with an ack.
3367  */
3368 int
3369 gld_ioctl(queue_t *q, mblk_t *mp)
3370 {
3371         struct iocblk *iocp;
3372         gld_t *gld;
3373         gld_mac_info_t *macinfo;
3374 
3375 #ifdef GLD_DEBUG
3376         if (gld_debug & GLDTRACE)
3377                 cmn_err(CE_NOTE, "gld_ioctl(%p %p)", (void *)q, (void *)mp);
3378 #endif
3379         gld = (gld_t *)q->q_ptr;
3380         iocp = (struct iocblk *)mp->b_rptr;
3381         switch (iocp->ioc_cmd) {
3382         case DLIOCRAW:          /* raw M_DATA mode */
3383                 gld->gld_flags |= GLD_RAW;
3384                 DB_TYPE(mp) = M_IOCACK;
3385                 qreply(q, mp);
3386                 break;
3387 
3388         case DL_IOC_HDR_INFO:   /* fastpath */
3389                 /*
3390                  * DL_IOC_HDR_INFO should only come from IP. The one
3391                  * initiated from user-land should not be allowed.
3392                  */
3393                 if ((gld_global_options & GLD_OPT_NO_FASTPATH) ||
3394                     (iocp->ioc_cr != kcred)) {
3395                         miocnak(q, mp, 0, EINVAL);
3396                         break;
3397                 }
3398                 gld_fastpath(gld, q, mp);
3399                 break;
3400 
3401         case DLIOCMARGININFO: { /* margin size */
3402                 int err;
3403 
3404                 if ((macinfo = gld->gld_mac_info) == NULL) {
3405                         miocnak(q, mp, 0, EINVAL);
3406                         break;
3407                 }
3408 
3409                 if ((err = miocpullup(mp, sizeof (uint32_t))) != 0) {
3410                         miocnak(q, mp, 0, err);
3411                         break;
3412                 }
3413 
3414                 *((uint32_t *)mp->b_cont->b_rptr) = macinfo->gldm_margin;
3415                 miocack(q, mp, sizeof (uint32_t), 0);
3416                 break;
3417         }
3418         default:
3419                 macinfo  = gld->gld_mac_info;
3420                 if (macinfo == NULL || macinfo->gldm_ioctl == NULL) {
3421                         miocnak(q, mp, 0, EINVAL);
3422                         break;
3423                 }
3424 
3425                 GLDM_LOCK(macinfo, RW_WRITER);
3426                 (void) (*macinfo->gldm_ioctl) (macinfo, q, mp);
3427                 GLDM_UNLOCK(macinfo);
3428                 break;
3429         }
3430         return (0);
3431 }
3432 
3433 /*
3434  * Since the rules for "fastpath" mode don't seem to be documented
3435  * anywhere, I will describe GLD's rules for fastpath users here:
3436  *
3437  * Once in this mode you remain there until close.
3438  * If you unbind/rebind you should get a new header using DL_IOC_HDR_INFO.
3439  * You must be bound (DL_IDLE) to transmit.
3440  * There are other rules not listed above.
3441  */
3442 static void
3443 gld_fastpath(gld_t *gld, queue_t *q, mblk_t *mp)
3444 {
3445         gld_interface_t *ifp;
3446         gld_mac_info_t *macinfo;
3447         dl_unitdata_req_t *dludp;
3448         mblk_t *nmp;
3449         t_scalar_t off, len;
3450         uint_t maclen;
3451         int error;
3452 
3453         if (gld->gld_state != DL_IDLE) {
3454                 miocnak(q, mp, 0, EINVAL);
3455                 return;
3456         }
3457 
3458         macinfo = gld->gld_mac_info;
3459         ASSERT(macinfo != NULL);
3460         maclen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen);
3461 
3462         error = miocpullup(mp, sizeof (dl_unitdata_req_t) + maclen);
3463         if (error != 0) {
3464                 miocnak(q, mp, 0, error);
3465                 return;
3466         }
3467 
3468         dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
3469         off = dludp->dl_dest_addr_offset;
3470         len = dludp->dl_dest_addr_length;
3471         if (dludp->dl_primitive != DL_UNITDATA_REQ ||
3472             !MBLKIN(mp->b_cont, off, len) || len != maclen) {
3473                 miocnak(q, mp, 0, EINVAL);
3474                 return;
3475         }
3476 
3477         /*
3478          * We take his fastpath request as a declaration that he will accept
3479          * M_DATA messages from us, whether or not we are willing to accept
3480          * them from him.  This allows us to have fastpath in one direction
3481          * (flow upstream) even on media with Source Routing, where we are
3482          * unable to provide a fixed MAC header to be prepended to downstream
3483          * flowing packets.  So we set GLD_FAST whether or not we decide to
3484          * allow him to send M_DATA down to us.
3485          */
3486         GLDM_LOCK(macinfo, RW_WRITER);
3487         gld->gld_flags |= GLD_FAST;
3488         GLDM_UNLOCK(macinfo);
3489 
3490         ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
3491 
3492         /* This will fail for Source Routing media */
3493         /* Also on Ethernet on 802.2 SAPs */
3494         if ((nmp = (*ifp->mkfastpath)(gld, mp)) == NULL) {
3495                 miocnak(q, mp, 0, ENOMEM);
3496                 return;
3497         }
3498 
3499         /*
3500          * Link new mblk in after the "request" mblks.
3501          */
3502         linkb(mp, nmp);
3503         miocack(q, mp, msgdsize(mp->b_cont), 0);
3504 }
3505 
3506 /*
3507  * gld_cmds (q, mp)
3508  *      process the DL commands as defined in dlpi.h
3509  *      note that the primitives return status which is passed back
3510  *      to the service procedure.  If the value is GLDE_RETRY, then
3511  *      it is assumed that processing must stop and the primitive has
3512  *      been put back onto the queue.  If the value is any other error,
3513  *      then an error ack is generated by the service procedure.
3514  */
3515 static int
3516 gld_cmds(queue_t *q, mblk_t *mp)
3517 {
3518         union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr;
3519         gld_t *gld = (gld_t *)(q->q_ptr);
3520         int result = DL_BADPRIM;
3521         int mblkl = MBLKL(mp);
3522         t_uscalar_t dlreq;
3523 
3524         /* Make sure we have at least dlp->dl_primitive */
3525         if (mblkl < sizeof (dlp->dl_primitive))
3526                 return (DL_BADPRIM);
3527 
3528         dlreq = dlp->dl_primitive;
3529 #ifdef  GLD_DEBUG
3530         if (gld_debug & GLDTRACE)
3531                 cmn_err(CE_NOTE,
3532                     "gld_cmds(%p, %p):dlp=%p, dlp->dl_primitive=%d",
3533                     (void *)q, (void *)mp, (void *)dlp, dlreq);
3534 #endif
3535 
3536         switch (dlreq) {
3537         case DL_UDQOS_REQ:
3538                 if (mblkl < DL_UDQOS_REQ_SIZE)
3539                         break;
3540                 result = gld_udqos(q, mp);
3541                 break;
3542 
3543         case DL_BIND_REQ:
3544                 if (mblkl < DL_BIND_REQ_SIZE)
3545                         break;
3546                 result = gld_bind(q, mp);
3547                 break;
3548 
3549         case DL_UNBIND_REQ:
3550                 if (mblkl < DL_UNBIND_REQ_SIZE)
3551                         break;
3552                 result = gld_unbind(q, mp);
3553                 break;
3554 
3555         case DL_UNITDATA_REQ:
3556                 if (mblkl < DL_UNITDATA_REQ_SIZE)
3557                         break;
3558                 result = gld_unitdata(q, mp);
3559                 break;
3560 
3561         case DL_INFO_REQ:
3562                 if (mblkl < DL_INFO_REQ_SIZE)
3563                         break;
3564                 result = gld_inforeq(q, mp);
3565                 break;
3566 
3567         case DL_ATTACH_REQ:
3568                 if (mblkl < DL_ATTACH_REQ_SIZE)
3569                         break;
3570                 if (gld->gld_style == DL_STYLE2)
3571                         result = gldattach(q, mp);
3572                 else
3573                         result = DL_NOTSUPPORTED;
3574                 break;
3575 
3576         case DL_DETACH_REQ:
3577                 if (mblkl < DL_DETACH_REQ_SIZE)
3578                         break;
3579                 if (gld->gld_style == DL_STYLE2)
3580                         result = gldunattach(q, mp);
3581                 else
3582                         result = DL_NOTSUPPORTED;
3583                 break;
3584 
3585         case DL_ENABMULTI_REQ:
3586                 if (mblkl < DL_ENABMULTI_REQ_SIZE)
3587                         break;
3588                 result = gld_enable_multi(q, mp);
3589                 break;
3590 
3591         case DL_DISABMULTI_REQ:
3592                 if (mblkl < DL_DISABMULTI_REQ_SIZE)
3593                         break;
3594                 result = gld_disable_multi(q, mp);
3595                 break;
3596 
3597         case DL_PHYS_ADDR_REQ:
3598                 if (mblkl < DL_PHYS_ADDR_REQ_SIZE)
3599                         break;
3600                 result = gld_physaddr(q, mp);
3601                 break;
3602 
3603         case DL_SET_PHYS_ADDR_REQ:
3604                 if (mblkl < DL_SET_PHYS_ADDR_REQ_SIZE)
3605                         break;
3606                 result = gld_setaddr(q, mp);
3607                 break;
3608 
3609         case DL_PROMISCON_REQ:
3610                 if (mblkl < DL_PROMISCON_REQ_SIZE)
3611                         break;
3612                 result = gld_promisc(q, mp, dlreq, B_TRUE);
3613                 break;
3614 
3615         case DL_PROMISCOFF_REQ:
3616                 if (mblkl < DL_PROMISCOFF_REQ_SIZE)
3617                         break;
3618                 result = gld_promisc(q, mp, dlreq, B_FALSE);
3619                 break;
3620 
3621         case DL_GET_STATISTICS_REQ:
3622                 if (mblkl < DL_GET_STATISTICS_REQ_SIZE)
3623                         break;
3624                 result = gld_get_statistics(q, mp);
3625                 break;
3626 
3627         case DL_CAPABILITY_REQ:
3628                 if (mblkl < DL_CAPABILITY_REQ_SIZE)
3629                         break;
3630                 result = gld_cap(q, mp);
3631                 break;
3632 
3633         case DL_NOTIFY_REQ:
3634                 if (mblkl < DL_NOTIFY_REQ_SIZE)
3635                         break;
3636                 result = gld_notify_req(q, mp);
3637                 break;
3638 
3639         case DL_XID_REQ:
3640         case DL_XID_RES:
3641         case DL_TEST_REQ:
3642         case DL_TEST_RES:
3643         case DL_CONTROL_REQ:
3644         case DL_PASSIVE_REQ:
3645                 result = DL_NOTSUPPORTED;
3646                 break;
3647 
3648         default:
3649 #ifdef  GLD_DEBUG
3650                 if (gld_debug & GLDERRS)
3651                         cmn_err(CE_WARN,
3652                             "gld_cmds: unknown M_PROTO message: %d",
3653                             dlreq);
3654 #endif
3655                 result = DL_BADPRIM;
3656         }
3657 
3658         return (result);
3659 }
3660 
3661 static int
3662 gld_cap(queue_t *q, mblk_t *mp)
3663 {
3664         gld_t *gld = (gld_t *)q->q_ptr;
3665         dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr;
3666 
3667         if (gld->gld_state == DL_UNATTACHED)
3668                 return (DL_OUTSTATE);
3669 
3670         if (dlp->dl_sub_length == 0)
3671                 return (gld_cap_ack(q, mp));
3672 
3673         return (gld_cap_enable(q, mp));
3674 }
3675 
3676 static int
3677 gld_cap_ack(queue_t *q, mblk_t *mp)
3678 {
3679         gld_t *gld = (gld_t *)q->q_ptr;
3680         gld_mac_info_t *macinfo = gld->gld_mac_info;
3681         gld_interface_t *ifp;
3682         dl_capability_ack_t *dlap;
3683         dl_capability_sub_t *dlsp;
3684         size_t size = sizeof (dl_capability_ack_t);
3685         size_t subsize = 0;
3686 
3687         ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
3688 
3689         if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY)
3690                 subsize += sizeof (dl_capability_sub_t) +
3691                     sizeof (dl_capab_hcksum_t);
3692         if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY)
3693                 subsize += sizeof (dl_capability_sub_t) +
3694                     sizeof (dl_capab_zerocopy_t);
3695         if (macinfo->gldm_options & GLDOPT_MDT)
3696                 subsize += (sizeof (dl_capability_sub_t) +
3697                     sizeof (dl_capab_mdt_t));
3698 
3699         if ((mp = mexchange(q, mp, size + subsize, M_PROTO,
3700             DL_CAPABILITY_ACK)) == NULL)
3701                 return (GLDE_OK);
3702 
3703         dlap = (dl_capability_ack_t *)mp->b_rptr;
3704         dlap->dl_sub_offset = 0;
3705         if ((dlap->dl_sub_length = subsize) != 0)
3706                 dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
3707         dlsp = (dl_capability_sub_t *)&dlap[1];
3708 
3709         if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY) {
3710                 dl_capab_hcksum_t *dlhp = (dl_capab_hcksum_t *)&dlsp[1];
3711 
3712                 dlsp->dl_cap = DL_CAPAB_HCKSUM;
3713                 dlsp->dl_length = sizeof (dl_capab_hcksum_t);
3714 
3715                 dlhp->hcksum_version = HCKSUM_VERSION_1;
3716 
3717                 dlhp->hcksum_txflags = 0;
3718                 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_PARTIAL)
3719                         dlhp->hcksum_txflags |= HCKSUM_INET_PARTIAL;
3720                 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V4)
3721                         dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V4;
3722                 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V6)
3723                         dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V6;
3724                 if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_IPHDR)
3725                         dlhp->hcksum_txflags |= HCKSUM_IPHDRCKSUM;
3726 
3727                 dlcapabsetqid(&(dlhp->hcksum_mid), RD(q));
3728                 dlsp = (dl_capability_sub_t *)&dlhp[1];
3729         }
3730 
3731         if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY) {
3732                 dl_capab_zerocopy_t *dlzp = (dl_capab_zerocopy_t *)&dlsp[1];
3733 
3734                 dlsp->dl_cap = DL_CAPAB_ZEROCOPY;
3735                 dlsp->dl_length = sizeof (dl_capab_zerocopy_t);
3736                 dlzp->zerocopy_version = ZEROCOPY_VERSION_1;
3737                 dlzp->zerocopy_flags = DL_CAPAB_VMSAFE_MEM;
3738 
3739                 dlcapabsetqid(&(dlzp->zerocopy_mid), RD(q));
3740                 dlsp = (dl_capability_sub_t *)&dlzp[1];
3741         }
3742 
3743         if (macinfo->gldm_options & GLDOPT_MDT) {
3744                 dl_capab_mdt_t *dlmp = (dl_capab_mdt_t *)&dlsp[1];
3745 
3746                 dlsp->dl_cap = DL_CAPAB_MDT;
3747                 dlsp->dl_length = sizeof (dl_capab_mdt_t);
3748 
3749                 dlmp->mdt_version = MDT_VERSION_2;
3750                 dlmp->mdt_max_pld = macinfo->gldm_mdt_segs;
3751                 dlmp->mdt_span_limit = macinfo->gldm_mdt_sgl;
3752                 dlcapabsetqid(&dlmp->mdt_mid, OTHERQ(q));
3753                 dlmp->mdt_flags = DL_CAPAB_MDT_ENABLE;
3754                 dlmp->mdt_hdr_head = ifp->hdr_size;
3755                 dlmp->mdt_hdr_tail = 0;
3756         }
3757 
3758         qreply(q, mp);
3759         return (GLDE_OK);
3760 }
3761 
3762 static int
3763 gld_cap_enable(queue_t *q, mblk_t *mp)
3764 {
3765         dl_capability_req_t *dlp;
3766         dl_capability_sub_t *dlsp;
3767         dl_capab_hcksum_t *dlhp;
3768         offset_t off;
3769         size_t len;
3770         size_t size;
3771         offset_t end;
3772 
3773         dlp = (dl_capability_req_t *)mp->b_rptr;
3774         dlp->dl_primitive = DL_CAPABILITY_ACK;
3775 
3776         off = dlp->dl_sub_offset;
3777         len = dlp->dl_sub_length;
3778 
3779         if (!MBLKIN(mp, off, len))
3780                 return (DL_BADPRIM);
3781 
3782         end = off + len;
3783         while (off < end) {
3784                 dlsp = (dl_capability_sub_t *)(mp->b_rptr + off);
3785                 size = sizeof (dl_capability_sub_t) + dlsp->dl_length;
3786                 if (off + size > end)
3787                         return (DL_BADPRIM);
3788 
3789                 switch (dlsp->dl_cap) {
3790                 case DL_CAPAB_HCKSUM:
3791                         dlhp = (dl_capab_hcksum_t *)&dlsp[1];
3792                         /* nothing useful we can do with the contents */
3793                         dlcapabsetqid(&(dlhp->hcksum_mid), RD(q));
3794                         break;
3795                 default:
3796                         break;
3797                 }
3798 
3799                 off += size;
3800         }
3801 
3802         qreply(q, mp);
3803         return (GLDE_OK);
3804 }
3805 
3806 /*
3807  * Send a copy of the DL_NOTIFY_IND message <mp> to each stream that has
3808  * requested the specific <notification> that the message carries AND is
3809  * eligible and ready to receive the notification immediately.
3810  *
3811  * This routine ignores flow control. Notifications will be sent regardless.
3812  *
3813  * In all cases, the original message passed in is freed at the end of
3814  * the routine.
3815  */
3816 static void
3817 gld_notify_qs(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t notification)
3818 {
3819         gld_mac_pvt_t *mac_pvt;
3820         gld_vlan_t *vlan;
3821         gld_t *gld;
3822         mblk_t *nmp;
3823         int i;
3824 
3825         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
3826 
3827         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3828 
3829         /*
3830          * Search all the streams attached to this macinfo looking
3831          * for those eligible to receive the present notification.
3832          */
3833         for (i = 0; i < VLAN_HASHSZ; i++) {
3834                 for (vlan = mac_pvt->vlan_hash[i];
3835                     vlan != NULL; vlan = vlan->gldv_next) {
3836                         for (gld = vlan->gldv_str_next;
3837                             gld != (gld_t *)&vlan->gldv_str_next;
3838                             gld = gld->gld_next) {
3839                                 ASSERT(gld->gld_qptr != NULL);
3840                                 ASSERT(gld->gld_state == DL_IDLE ||
3841                                     gld->gld_state == DL_UNBOUND);
3842                                 ASSERT(gld->gld_mac_info == macinfo);
3843 
3844                                 if (gld->gld_flags & GLD_STR_CLOSING)
3845                                         continue; /* not eligible - skip */
3846                                 if (!(notification & gld->gld_notifications))
3847                                         continue; /* not wanted - skip */
3848                                 if ((nmp = dupmsg(mp)) == NULL)
3849                                         continue; /* can't copy - skip */
3850 
3851                                 /*
3852                                  * All OK; send dup'd notification up this
3853                                  * stream
3854                                  */
3855                                 qreply(WR(gld->gld_qptr), nmp);
3856                         }
3857                 }
3858         }
3859 
3860         /*
3861          * Drop the original message block now
3862          */
3863         freemsg(mp);
3864 }
3865 
3866 /*
3867  * For each (understood) bit in the <notifications> argument, contruct
3868  * a DL_NOTIFY_IND message and send it to the specified <q>, or to all
3869  * eligible queues if <q> is NULL.
3870  */
3871 static void
3872 gld_notify_ind(gld_mac_info_t *macinfo, uint32_t notifications, queue_t *q)
3873 {
3874         gld_mac_pvt_t *mac_pvt;
3875         dl_notify_ind_t *dlnip;
3876         struct gld_stats *stats;
3877         mblk_t *mp;
3878         size_t size;
3879         uint32_t bit;
3880 
3881         GLDM_LOCK(macinfo, RW_WRITER);
3882 
3883         /*
3884          * The following cases shouldn't happen, but just in case the
3885          * MAC driver calls gld_linkstate() at an inappropriate time, we
3886          * check anyway ...
3887          */
3888         if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) {
3889                 GLDM_UNLOCK(macinfo);
3890                 return;                         /* not ready yet        */
3891         }
3892 
3893         if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
3894                 GLDM_UNLOCK(macinfo);
3895                 return;                         /* not ready anymore    */
3896         }
3897 
3898         /*
3899          * Make sure the kstats are up to date, 'cos we use some of
3900          * the kstat values below, specifically the link speed ...
3901          */
3902         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3903         stats = mac_pvt->statistics;
3904         if (macinfo->gldm_get_stats)
3905                 (void) (*macinfo->gldm_get_stats)(macinfo, stats);
3906 
3907         for (bit = 1; notifications != 0; bit <<= 1) {
3908                 if ((notifications & bit) == 0)
3909                         continue;
3910                 notifications &= ~bit;
3911 
3912                 size = DL_NOTIFY_IND_SIZE;
3913                 if (bit == DL_NOTE_PHYS_ADDR)
3914                         size += macinfo->gldm_addrlen;
3915                 if ((mp = allocb(size, BPRI_MED)) == NULL)
3916                         continue;
3917 
3918                 mp->b_datap->db_type = M_PROTO;
3919                 mp->b_wptr = mp->b_rptr + size;
3920                 dlnip = (dl_notify_ind_t *)mp->b_rptr;
3921                 dlnip->dl_primitive = DL_NOTIFY_IND;
3922                 dlnip->dl_notification = 0;
3923                 dlnip->dl_data = 0;
3924                 dlnip->dl_addr_length = 0;
3925                 dlnip->dl_addr_offset = 0;
3926 
3927                 switch (bit) {
3928                 case DL_NOTE_PROMISC_ON_PHYS:
3929                 case DL_NOTE_PROMISC_OFF_PHYS:
3930                         if (mac_pvt->nprom != 0)
3931                                 dlnip->dl_notification = bit;
3932                         break;
3933 
3934                 case DL_NOTE_LINK_DOWN:
3935                         if (macinfo->gldm_linkstate == GLD_LINKSTATE_DOWN)
3936                                 dlnip->dl_notification = bit;
3937                         break;
3938 
3939                 case DL_NOTE_LINK_UP:
3940                         if (macinfo->gldm_linkstate == GLD_LINKSTATE_UP)
3941                                 dlnip->dl_notification = bit;
3942                         break;
3943 
3944                 case DL_NOTE_SPEED:
3945                         /*
3946                          * Conversion required here:
3947                          *      GLD keeps the speed in bit/s in a uint64
3948                          *      DLPI wants it in kb/s in a uint32
3949                          * Fortunately this is still big enough for 10Gb/s!
3950                          */
3951                         dlnip->dl_notification = bit;
3952                         dlnip->dl_data = stats->glds_speed/1000ULL;
3953                         break;
3954 
3955                 case DL_NOTE_PHYS_ADDR:
3956                         dlnip->dl_notification = bit;
3957                         dlnip->dl_data = DL_CURR_PHYS_ADDR;
3958                         dlnip->dl_addr_offset = sizeof (dl_notify_ind_t);
3959                         dlnip->dl_addr_length = macinfo->gldm_addrlen +
3960                             abs(macinfo->gldm_saplen);
3961                         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3962                         mac_copy(mac_pvt->curr_macaddr,
3963                             mp->b_rptr + sizeof (dl_notify_ind_t),
3964                             macinfo->gldm_addrlen);
3965                         break;
3966 
3967                 default:
3968                         break;
3969                 }
3970 
3971                 if (dlnip->dl_notification == 0)
3972                         freemsg(mp);
3973                 else if (q != NULL)
3974                         qreply(q, mp);
3975                 else
3976                         gld_notify_qs(macinfo, mp, bit);
3977         }
3978 
3979         GLDM_UNLOCK(macinfo);
3980 }
3981 
3982 /*
3983  * gld_notify_req - handle a DL_NOTIFY_REQ message
3984  */
3985 static int
3986 gld_notify_req(queue_t *q, mblk_t *mp)
3987 {
3988         gld_t *gld = (gld_t *)q->q_ptr;
3989         gld_mac_info_t *macinfo;
3990         gld_mac_pvt_t *pvt;
3991         dl_notify_req_t *dlnrp;
3992         dl_notify_ack_t *dlnap;
3993 
3994         ASSERT(gld != NULL);
3995         ASSERT(gld->gld_qptr == RD(q));
3996 
3997         dlnrp = (dl_notify_req_t *)mp->b_rptr;
3998 
3999 #ifdef GLD_DEBUG
4000         if (gld_debug & GLDTRACE)
4001                 cmn_err(CE_NOTE, "gld_notify_req(%p %p)",
4002                     (void *)q, (void *)mp);
4003 #endif
4004 
4005         if (gld->gld_state == DL_UNATTACHED) {
4006 #ifdef GLD_DEBUG
4007                 if (gld_debug & GLDERRS)
4008                         cmn_err(CE_NOTE, "gld_notify_req: wrong state (%d)",
4009                             gld->gld_state);
4010 #endif
4011                 return (DL_OUTSTATE);
4012         }
4013 
4014         /*
4015          * Remember what notifications are required by this stream
4016          */
4017         macinfo = gld->gld_mac_info;
4018         pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4019 
4020         gld->gld_notifications = dlnrp->dl_notifications & pvt->notifications;
4021 
4022         /*
4023          * The return DL_NOTIFY_ACK carries the bitset of notifications
4024          * that this driver can provide, independently of which ones have
4025          * previously been or are now being requested.
4026          */
4027         if ((mp = mexchange(q, mp, sizeof (dl_notify_ack_t), M_PCPROTO,
4028             DL_NOTIFY_ACK)) == NULL)
4029                 return (DL_SYSERR);
4030 
4031         dlnap = (dl_notify_ack_t *)mp->b_rptr;
4032         dlnap->dl_notifications = pvt->notifications;
4033         qreply(q, mp);
4034 
4035         /*
4036          * A side effect of a DL_NOTIFY_REQ is that after the DL_NOTIFY_ACK
4037          * reply, the the requestor gets zero or more DL_NOTIFY_IND messages
4038          * that provide the current status.
4039          */
4040         gld_notify_ind(macinfo, gld->gld_notifications, q);
4041 
4042         return (GLDE_OK);
4043 }
4044 
4045 /*
4046  * gld_linkstate()
4047  *      Called by driver to tell GLD the state of the physical link.
4048  *      As a side effect, sends a DL_NOTE_LINK_UP or DL_NOTE_LINK_DOWN
4049  *      notification to each client that has previously requested such
4050  *      notifications
4051  */
4052 void
4053 gld_linkstate(gld_mac_info_t *macinfo, int32_t newstate)
4054 {
4055         uint32_t notification;
4056 
4057         switch (newstate) {
4058         default:
4059                 return;
4060 
4061         case GLD_LINKSTATE_DOWN:
4062                 notification = DL_NOTE_LINK_DOWN;
4063                 break;
4064 
4065         case GLD_LINKSTATE_UP:
4066                 notification = DL_NOTE_LINK_UP | DL_NOTE_SPEED;
4067                 break;
4068 
4069         case GLD_LINKSTATE_UNKNOWN:
4070                 notification = 0;
4071                 break;
4072         }
4073 
4074         GLDM_LOCK(macinfo, RW_WRITER);
4075         if (macinfo->gldm_linkstate == newstate)
4076                 notification = 0;
4077         else
4078                 macinfo->gldm_linkstate = newstate;
4079         GLDM_UNLOCK(macinfo);
4080 
4081         if (notification)
4082                 gld_notify_ind(macinfo, notification, NULL);
4083 }
4084 
4085 /*
4086  * gld_udqos - set the current QoS parameters (priority only at the moment).
4087  */
4088 static int
4089 gld_udqos(queue_t *q, mblk_t *mp)
4090 {
4091         dl_udqos_req_t *dlp;
4092         gld_t  *gld = (gld_t *)q->q_ptr;
4093         int off;
4094         int len;
4095         dl_qos_cl_sel1_t *selp;
4096 
4097         ASSERT(gld);
4098         ASSERT(gld->gld_qptr == RD(q));
4099 
4100 #ifdef GLD_DEBUG
4101         if (gld_debug & GLDTRACE)
4102                 cmn_err(CE_NOTE, "gld_udqos(%p %p)", (void *)q, (void *)mp);
4103 #endif
4104 
4105         if (gld->gld_state != DL_IDLE) {
4106 #ifdef GLD_DEBUG
4107                 if (gld_debug & GLDERRS)
4108                         cmn_err(CE_NOTE, "gld_udqos: wrong state (%d)",
4109                             gld->gld_state);
4110 #endif
4111                 return (DL_OUTSTATE);
4112         }
4113 
4114         dlp = (dl_udqos_req_t *)mp->b_rptr;
4115         off = dlp->dl_qos_offset;
4116         len = dlp->dl_qos_length;
4117 
4118         if (len != sizeof (dl_qos_cl_sel1_t) || !MBLKIN(mp, off, len))
4119                 return (DL_BADQOSTYPE);
4120 
4121         selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off);
4122         if (selp->dl_qos_type != DL_QOS_CL_SEL1)
4123                 return (DL_BADQOSTYPE);
4124 
4125         if (selp->dl_trans_delay != 0 &&
4126             selp->dl_trans_delay != DL_QOS_DONT_CARE)
4127                 return (DL_BADQOSPARAM);
4128         if (selp->dl_protection != 0 &&
4129             selp->dl_protection != DL_QOS_DONT_CARE)
4130                 return (DL_BADQOSPARAM);
4131         if (selp->dl_residual_error != 0 &&
4132             selp->dl_residual_error != DL_QOS_DONT_CARE)
4133                 return (DL_BADQOSPARAM);
4134         if (selp->dl_priority < 0 || selp->dl_priority > 7)
4135                 return (DL_BADQOSPARAM);
4136 
4137         gld->gld_upri = selp->dl_priority;
4138 
4139         dlokack(q, mp, DL_UDQOS_REQ);
4140         return (GLDE_OK);
4141 }
4142 
4143 static mblk_t *
4144 gld_bindack(queue_t *q, mblk_t *mp)
4145 {
4146         gld_t *gld = (gld_t *)q->q_ptr;
4147         gld_mac_info_t *macinfo = gld->gld_mac_info;
4148         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4149         dl_bind_ack_t *dlp;
4150         size_t size;
4151         t_uscalar_t addrlen;
4152         uchar_t *sapp;
4153 
4154         addrlen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen);
4155         size = sizeof (dl_bind_ack_t) + addrlen;
4156         if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL)
4157                 return (NULL);
4158 
4159         dlp = (dl_bind_ack_t *)mp->b_rptr;
4160         dlp->dl_sap = gld->gld_sap;
4161         dlp->dl_addr_length = addrlen;
4162         dlp->dl_addr_offset = sizeof (dl_bind_ack_t);
4163         dlp->dl_max_conind = 0;
4164         dlp->dl_xidtest_flg = 0;
4165 
4166         mac_copy(mac_pvt->curr_macaddr, (uchar_t *)&dlp[1],
4167             macinfo->gldm_addrlen);
4168         sapp = mp->b_rptr + dlp->dl_addr_offset + macinfo->gldm_addrlen;
4169         *(ushort_t *)sapp = gld->gld_sap;
4170 
4171         return (mp);
4172 }
4173 
4174 /*
4175  * gld_bind - determine if a SAP is already allocated and whether it is legal
4176  * to do the bind at this time
4177  */
4178 static int
4179 gld_bind(queue_t *q, mblk_t *mp)
4180 {
4181         ulong_t sap;
4182         dl_bind_req_t *dlp;
4183         gld_t *gld = (gld_t *)q->q_ptr;
4184         gld_mac_info_t *macinfo = gld->gld_mac_info;
4185 
4186         ASSERT(gld);
4187         ASSERT(gld->gld_qptr == RD(q));
4188 
4189 #ifdef GLD_DEBUG
4190         if (gld_debug & GLDTRACE)
4191                 cmn_err(CE_NOTE, "gld_bind(%p %p)", (void *)q, (void *)mp);
4192 #endif
4193 
4194         dlp = (dl_bind_req_t *)mp->b_rptr;
4195         sap = dlp->dl_sap;
4196 
4197 #ifdef GLD_DEBUG
4198         if (gld_debug & GLDPROT)
4199                 cmn_err(CE_NOTE, "gld_bind: lsap=%lx", sap);
4200 #endif
4201 
4202         if (gld->gld_state != DL_UNBOUND) {
4203 #ifdef GLD_DEBUG
4204                 if (gld_debug & GLDERRS)
4205                         cmn_err(CE_NOTE, "gld_bind: bound or not attached (%d)",
4206                             gld->gld_state);
4207 #endif
4208                 return (DL_OUTSTATE);
4209         }
4210         ASSERT(macinfo);
4211 
4212         if (dlp->dl_service_mode != DL_CLDLS) {
4213                 return (DL_UNSUPPORTED);
4214         }
4215         if (dlp->dl_xidtest_flg & (DL_AUTO_XID | DL_AUTO_TEST)) {
4216                 return (DL_NOAUTO);
4217         }
4218 
4219         /*
4220          * Check sap validity and decide whether this stream accepts
4221          * IEEE 802.2 (LLC) packets.
4222          */
4223         if (sap > ETHERTYPE_MAX)
4224                 return (DL_BADSAP);
4225 
4226         /*
4227          * Decide whether the SAP value selects EtherType encoding/decoding.
4228          * For compatibility with monolithic ethernet drivers, the range of
4229          * SAP values is different for DL_ETHER media.
4230          */
4231         switch (macinfo->gldm_type) {
4232         case DL_ETHER:
4233                 gld->gld_ethertype = (sap > ETHERMTU);
4234                 break;
4235         default:
4236                 gld->gld_ethertype = (sap > GLD_MAX_802_SAP);
4237                 break;
4238         }
4239 
4240         /* if we get to here, then the SAP is legal enough */
4241         GLDM_LOCK(macinfo, RW_WRITER);
4242         gld->gld_state = DL_IDLE;    /* bound and ready */
4243         gld->gld_sap = sap;
4244         if ((macinfo->gldm_type == DL_ETHER) && (sap == ETHERTYPE_VLAN))
4245                 ((gld_vlan_t *)gld->gld_vlan)->gldv_nvlan_sap++;
4246         gld_set_ipq(gld);
4247 
4248 #ifdef GLD_DEBUG
4249         if (gld_debug & GLDPROT)
4250                 cmn_err(CE_NOTE, "gld_bind: ok - sap = %d", gld->gld_sap);
4251 #endif
4252 
4253         /* ACK the BIND */
4254         mp = gld_bindack(q, mp);
4255         GLDM_UNLOCK(macinfo);
4256 
4257         if (mp != NULL) {
4258                 qreply(q, mp);
4259                 return (GLDE_OK);
4260         }
4261 
4262         return (DL_SYSERR);
4263 }
4264 
4265 /*
4266  * gld_unbind - perform an unbind of an LSAP or ether type on the stream.
4267  * The stream is still open and can be re-bound.
4268  */
4269 static int
4270 gld_unbind(queue_t *q, mblk_t *mp)
4271 {
4272         gld_t *gld = (gld_t *)q->q_ptr;
4273         gld_mac_info_t *macinfo = gld->gld_mac_info;
4274 
4275         ASSERT(gld);
4276 
4277 #ifdef GLD_DEBUG
4278         if (gld_debug & GLDTRACE)
4279                 cmn_err(CE_NOTE, "gld_unbind(%p %p)", (void *)q, (void *)mp);
4280 #endif
4281 
4282         if (gld->gld_state != DL_IDLE) {
4283 #ifdef GLD_DEBUG
4284                 if (gld_debug & GLDERRS)
4285                         cmn_err(CE_NOTE, "gld_unbind: wrong state (%d)",
4286                             gld->gld_state);
4287 #endif
4288                 return (DL_OUTSTATE);
4289         }
4290         ASSERT(macinfo);
4291 
4292         /*
4293          * Avoid unbinding (DL_UNBIND_REQ) while FAST/RAW is inside wput.
4294          * See comments above gld_start().
4295          */
4296         gld->gld_in_unbind = B_TRUE; /* disallow wput=>start */
4297         membar_enter();
4298         if (gld->gld_wput_count != 0) {
4299                 gld->gld_in_unbind = B_FALSE;
4300                 ASSERT(mp);             /* we didn't come from close */
4301 #ifdef GLD_DEBUG
4302                 if (gld_debug & GLDETRACE)
4303                         cmn_err(CE_NOTE, "gld_unbind: defer for wput");
4304 #endif
4305                 (void) putbq(q, mp);
4306                 qenable(q);             /* try again soon */
4307                 return (GLDE_RETRY);
4308         }
4309 
4310         GLDM_LOCK(macinfo, RW_WRITER);
4311         if ((macinfo->gldm_type == DL_ETHER) &&
4312             (gld->gld_sap == ETHERTYPE_VLAN)) {
4313                 ((gld_vlan_t *)gld->gld_vlan)->gldv_nvlan_sap--;
4314         }
4315         gld->gld_state = DL_UNBOUND;
4316         gld->gld_sap = 0;
4317         gld_set_ipq(gld);
4318         GLDM_UNLOCK(macinfo);
4319 
4320         membar_exit();
4321         gld->gld_in_unbind = B_FALSE;
4322 
4323         /* mp is NULL if we came from close */
4324         if (mp) {
4325                 gld_flushqueue(q);      /* flush the queues */
4326                 dlokack(q, mp, DL_UNBIND_REQ);
4327         }
4328         return (GLDE_OK);
4329 }
4330 
4331 /*
4332  * gld_inforeq - generate the response to an info request
4333  */
4334 static int
4335 gld_inforeq(queue_t *q, mblk_t *mp)
4336 {
4337         gld_t           *gld;
4338         dl_info_ack_t   *dlp;
4339         int             bufsize;
4340         glddev_t        *glddev;
4341         gld_mac_info_t  *macinfo;
4342         gld_mac_pvt_t   *mac_pvt;
4343         int             sel_offset = 0;
4344         int             range_offset = 0;
4345         int             addr_offset;
4346         int             addr_length;
4347         int             sap_length;
4348         int             brdcst_offset;
4349         int             brdcst_length;
4350         uchar_t         *sapp;
4351 
4352 #ifdef GLD_DEBUG
4353         if (gld_debug & GLDTRACE)
4354                 cmn_err(CE_NOTE, "gld_inforeq(%p %p)", (void *)q, (void *)mp);
4355 #endif
4356         gld = (gld_t *)q->q_ptr;
4357         ASSERT(gld);
4358         glddev = gld->gld_device;
4359         ASSERT(glddev);
4360 
4361         if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) {
4362                 macinfo = gld->gld_mac_info;
4363                 ASSERT(macinfo != NULL);
4364 
4365                 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4366 
4367                 addr_length = macinfo->gldm_addrlen;
4368                 sap_length = macinfo->gldm_saplen;
4369                 brdcst_length = macinfo->gldm_addrlen;
4370         } else {
4371                 addr_length = glddev->gld_addrlen;
4372                 sap_length = glddev->gld_saplen;
4373                 brdcst_length = glddev->gld_addrlen;
4374         }
4375 
4376         bufsize = sizeof (dl_info_ack_t);
4377 
4378         addr_offset = bufsize;
4379         bufsize += addr_length;
4380         bufsize += abs(sap_length);
4381 
4382         brdcst_offset = bufsize;
4383         bufsize += brdcst_length;
4384 
4385         if (((gld_vlan_t *)gld->gld_vlan) != NULL) {
4386                 sel_offset = P2ROUNDUP(bufsize, sizeof (int64_t));
4387                 bufsize = sel_offset + sizeof (dl_qos_cl_sel1_t);
4388 
4389                 range_offset = P2ROUNDUP(bufsize, sizeof (int64_t));
4390                 bufsize = range_offset + sizeof (dl_qos_cl_range1_t);
4391         }
4392 
4393         if ((mp = mexchange(q, mp, bufsize, M_PCPROTO, DL_INFO_ACK)) == NULL)
4394                 return (GLDE_OK);       /* nothing more to be done */
4395 
4396         bzero(mp->b_rptr, bufsize);
4397 
4398         dlp = (dl_info_ack_t *)mp->b_rptr;
4399         dlp->dl_primitive = DL_INFO_ACK;
4400         dlp->dl_version = DL_VERSION_2;
4401         dlp->dl_service_mode = DL_CLDLS;
4402         dlp->dl_current_state = gld->gld_state;
4403         dlp->dl_provider_style = gld->gld_style;
4404 
4405         if (sel_offset != 0) {
4406                 dl_qos_cl_sel1_t        *selp;
4407                 dl_qos_cl_range1_t      *rangep;
4408 
4409                 ASSERT(range_offset != 0);
4410 
4411                 dlp->dl_qos_offset = sel_offset;
4412                 dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
4413                 dlp->dl_qos_range_offset = range_offset;
4414                 dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
4415 
4416                 selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + sel_offset);
4417                 selp->dl_qos_type = DL_QOS_CL_SEL1;
4418                 selp->dl_priority = gld->gld_upri;
4419 
4420                 rangep = (dl_qos_cl_range1_t *)(mp->b_rptr + range_offset);
4421                 rangep->dl_qos_type = DL_QOS_CL_RANGE1;
4422                 rangep->dl_priority.dl_min = 0;
4423                 rangep->dl_priority.dl_max = 7;
4424         }
4425 
4426         if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) {
4427                 dlp->dl_min_sdu = macinfo->gldm_minpkt;
4428                 dlp->dl_max_sdu = macinfo->gldm_maxpkt;
4429                 dlp->dl_mac_type = macinfo->gldm_type;
4430                 dlp->dl_addr_length = addr_length + abs(sap_length);
4431                 dlp->dl_sap_length = sap_length;
4432 
4433                 if (gld->gld_state == DL_IDLE) {
4434                         /*
4435                          * If we are bound to a non-LLC SAP on any medium
4436                          * other than Ethernet, then we need room for a
4437                          * SNAP header.  So we have to adjust the MTU size
4438                          * accordingly.  XXX I suppose this should be done
4439                          * in gldutil.c, but it seems likely that this will
4440                          * always be true for everything GLD supports but
4441                          * Ethernet.  Check this if you add another medium.
4442                          */
4443                         if ((macinfo->gldm_type == DL_TPR ||
4444                             macinfo->gldm_type == DL_FDDI) &&
4445                             gld->gld_ethertype)
4446                                 dlp->dl_max_sdu -= LLC_SNAP_HDR_LEN;
4447 
4448                         /* copy macaddr and sap */
4449                         dlp->dl_addr_offset = addr_offset;
4450 
4451                         mac_copy(mac_pvt->curr_macaddr, mp->b_rptr +
4452                             addr_offset, macinfo->gldm_addrlen);
4453                         sapp = mp->b_rptr + addr_offset +
4454                             macinfo->gldm_addrlen;
4455                         *(ushort_t *)sapp = gld->gld_sap;
4456                 } else {
4457                         dlp->dl_addr_offset = 0;
4458                 }
4459 
4460                 /* copy broadcast addr */
4461                 dlp->dl_brdcst_addr_length = macinfo->gldm_addrlen;
4462                 dlp->dl_brdcst_addr_offset = brdcst_offset;
4463                 mac_copy((caddr_t)macinfo->gldm_broadcast_addr,
4464                     mp->b_rptr + brdcst_offset, brdcst_length);
4465         } else {
4466                 /*
4467                  * No PPA is attached.
4468                  * The best we can do is use the values provided
4469                  * by the first mac that called gld_register.
4470                  */
4471                 dlp->dl_min_sdu = glddev->gld_minsdu;
4472                 dlp->dl_max_sdu = glddev->gld_maxsdu;
4473                 dlp->dl_mac_type = glddev->gld_type;
4474                 dlp->dl_addr_length = addr_length + abs(sap_length);
4475                 dlp->dl_sap_length = sap_length;
4476                 dlp->dl_addr_offset = 0;
4477                 dlp->dl_brdcst_addr_offset = brdcst_offset;
4478                 dlp->dl_brdcst_addr_length = brdcst_length;
4479                 mac_copy((caddr_t)glddev->gld_broadcast,
4480                     mp->b_rptr + brdcst_offset, brdcst_length);
4481         }
4482         qreply(q, mp);
4483         return (GLDE_OK);
4484 }
4485 
4486 /*
4487  * gld_unitdata (q, mp)
4488  * send a datagram.  Destination address/lsap is in M_PROTO
4489  * message (first mblock), data is in remainder of message.
4490  *
4491  */
4492 static int
4493 gld_unitdata(queue_t *q, mblk_t *mp)
4494 {
4495         gld_t *gld = (gld_t *)q->q_ptr;
4496         dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
4497         gld_mac_info_t *macinfo = gld->gld_mac_info;
4498         size_t  msglen;
4499         mblk_t  *nmp;
4500         gld_interface_t *ifp;
4501         uint32_t start;
4502         uint32_t stuff;
4503         uint32_t end;
4504         uint32_t value;
4505         uint32_t flags;
4506         uint32_t upri;
4507 
4508 #ifdef GLD_DEBUG
4509         if (gld_debug & GLDTRACE)
4510                 cmn_err(CE_NOTE, "gld_unitdata(%p %p)", (void *)q, (void *)mp);
4511 #endif
4512 
4513         if (gld->gld_state != DL_IDLE) {
4514 #ifdef GLD_DEBUG
4515                 if (gld_debug & GLDERRS)
4516                         cmn_err(CE_NOTE, "gld_unitdata: wrong state (%d)",
4517                             gld->gld_state);
4518 #endif
4519                 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4520                     dlp->dl_dest_addr_length, DL_OUTSTATE, 0);
4521                 return (GLDE_OK);
4522         }
4523         ASSERT(macinfo != NULL);
4524 
4525         if (!MBLKIN(mp, dlp->dl_dest_addr_offset, dlp->dl_dest_addr_length) ||
4526             dlp->dl_dest_addr_length !=
4527             macinfo->gldm_addrlen + abs(macinfo->gldm_saplen)) {
4528                 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4529                     dlp->dl_dest_addr_length, DL_BADADDR, 0);
4530                 return (GLDE_OK);
4531         }
4532 
4533         upri = dlp->dl_priority.dl_max;
4534 
4535         msglen = msgdsize(mp);
4536         if (msglen == 0 || msglen > macinfo->gldm_maxpkt) {
4537 #ifdef GLD_DEBUG
4538                 if (gld_debug & GLDERRS)
4539                         cmn_err(CE_NOTE, "gld_unitdata: bad msglen (%d)",
4540                             (int)msglen);
4541 #endif
4542                 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4543                     dlp->dl_dest_addr_length, DL_BADDATA, 0);
4544                 return (GLDE_OK);
4545         }
4546 
4547         ASSERT(mp->b_cont != NULL);  /* because msgdsize(mp) is nonzero */
4548 
4549         ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
4550 
4551         /* grab any checksum information that may be present */
4552         hcksum_retrieve(mp->b_cont, NULL, NULL, &start, &stuff, &end,
4553             &value, &flags);
4554 
4555         /*
4556          * Prepend a valid header for transmission
4557          */
4558         if ((nmp = (*ifp->mkunitdata)(gld, mp)) == NULL) {
4559 #ifdef GLD_DEBUG
4560                 if (gld_debug & GLDERRS)
4561                         cmn_err(CE_NOTE, "gld_unitdata: mkunitdata failed.");
4562 #endif
4563                 dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4564                     dlp->dl_dest_addr_length, DL_SYSERR, ENOSR);
4565                 return (GLDE_OK);
4566         }
4567 
4568         /* apply any checksum information to the first block in the chain */
4569         (void) hcksum_assoc(nmp, NULL, NULL, start, stuff, end, value,
4570             flags, 0);
4571 
4572         GLD_CLEAR_MBLK_VTAG(nmp);
4573         if (gld_start(q, nmp, GLD_WSRV, upri) == GLD_NORESOURCES) {
4574                 qenable(q);
4575                 return (GLDE_RETRY);
4576         }
4577 
4578         return (GLDE_OK);
4579 }
4580 
4581 /*
4582  * gldattach(q, mp)
4583  * DLPI DL_ATTACH_REQ
4584  * this attaches the stream to a PPA
4585  */
4586 static int
4587 gldattach(queue_t *q, mblk_t *mp)
4588 {
4589         dl_attach_req_t *at;
4590         gld_mac_info_t *macinfo;
4591         gld_t  *gld = (gld_t *)q->q_ptr;
4592         glddev_t *glddev;
4593         gld_mac_pvt_t *mac_pvt;
4594         uint32_t ppa;
4595         uint32_t vid;
4596         gld_vlan_t *vlan;
4597 
4598         at = (dl_attach_req_t *)mp->b_rptr;
4599 
4600         if (gld->gld_state != DL_UNATTACHED)
4601                 return (DL_OUTSTATE);
4602 
4603         ASSERT(!gld->gld_mac_info);
4604 
4605         ppa = at->dl_ppa % GLD_VLAN_SCALE;   /* 0 .. 999     */
4606         vid = at->dl_ppa / GLD_VLAN_SCALE;   /* 0 .. 4094    */
4607         if (vid > VLAN_VID_MAX)
4608                 return (DL_BADPPA);
4609 
4610         glddev = gld->gld_device;
4611         mutex_enter(&glddev->gld_devlock);
4612         for (macinfo = glddev->gld_mac_next;
4613             macinfo != (gld_mac_info_t *)&glddev->gld_mac_next;
4614             macinfo = macinfo->gldm_next) {
4615                 int inst;
4616 
4617                 ASSERT(macinfo != NULL);
4618                 if (macinfo->gldm_ppa != ppa)
4619                         continue;
4620 
4621                 if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
4622                         continue;       /* this one's not ready yet */
4623 
4624                 /*
4625                  * VLAN sanity check
4626                  */
4627                 if (vid != VLAN_VID_NONE && !VLAN_CAPABLE(macinfo)) {
4628                         mutex_exit(&glddev->gld_devlock);
4629                         return (DL_BADPPA);
4630                 }
4631 
4632                 /*
4633                  * We found the correct PPA, hold the instance
4634                  */
4635                 inst = ddi_get_instance(macinfo->gldm_devinfo);
4636                 if (inst == -1 || qassociate(q, inst) != 0) {
4637                         mutex_exit(&glddev->gld_devlock);
4638                         return (DL_BADPPA);
4639                 }
4640 
4641                 /* Take the stream off the per-driver-class list */
4642                 gldremque(gld);
4643 
4644                 /*
4645                  * We must hold the lock to prevent multiple calls
4646                  * to the reset and start routines.
4647                  */
4648                 GLDM_LOCK(macinfo, RW_WRITER);
4649 
4650                 gld->gld_mac_info = macinfo;
4651 
4652                 if (macinfo->gldm_send_tagged != NULL)
4653                         gld->gld_send = macinfo->gldm_send_tagged;
4654                 else
4655                         gld->gld_send = macinfo->gldm_send;
4656 
4657                 if ((vlan = gld_get_vlan(macinfo, vid)) == NULL) {
4658                         GLDM_UNLOCK(macinfo);
4659                         gldinsque(gld, glddev->gld_str_prev);
4660                         mutex_exit(&glddev->gld_devlock);
4661                         (void) qassociate(q, -1);
4662                         return (DL_BADPPA);
4663                 }
4664 
4665                 mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4666                 if (!mac_pvt->started) {
4667                         if (gld_start_mac(macinfo) != GLD_SUCCESS) {
4668                                 gld_rem_vlan(vlan);
4669                                 GLDM_UNLOCK(macinfo);
4670                                 gldinsque(gld, glddev->gld_str_prev);
4671                                 mutex_exit(&glddev->gld_devlock);
4672                                 dlerrorack(q, mp, DL_ATTACH_REQ, DL_SYSERR,
4673                                     EIO);
4674                                 (void) qassociate(q, -1);
4675                                 return (GLDE_OK);
4676                         }
4677                 }
4678 
4679                 gld->gld_vlan = vlan;
4680                 vlan->gldv_nstreams++;
4681                 gldinsque(gld, vlan->gldv_str_prev);
4682                 gld->gld_state = DL_UNBOUND;
4683                 GLDM_UNLOCK(macinfo);
4684 
4685 #ifdef GLD_DEBUG
4686                 if (gld_debug & GLDPROT) {
4687                         cmn_err(CE_NOTE, "gldattach(%p, %p, PPA = %d)",
4688                             (void *)q, (void *)mp, macinfo->gldm_ppa);
4689                 }
4690 #endif
4691                 mutex_exit(&glddev->gld_devlock);
4692                 dlokack(q, mp, DL_ATTACH_REQ);
4693                 return (GLDE_OK);
4694         }
4695         mutex_exit(&glddev->gld_devlock);
4696         return (DL_BADPPA);
4697 }
4698 
4699 /*
4700  * gldunattach(q, mp)
4701  * DLPI DL_DETACH_REQ
4702  * detaches the mac layer from the stream
4703  */
4704 int
4705 gldunattach(queue_t *q, mblk_t *mp)
4706 {
4707         gld_t  *gld = (gld_t *)q->q_ptr;
4708         glddev_t *glddev = gld->gld_device;
4709         gld_mac_info_t *macinfo = gld->gld_mac_info;
4710         int     state = gld->gld_state;
4711         int     i;
4712         gld_mac_pvt_t *mac_pvt;
4713         gld_vlan_t *vlan;
4714         boolean_t phys_off;
4715         boolean_t mult_off;
4716         int op = GLD_MAC_PROMISC_NOOP;
4717 
4718         if (state != DL_UNBOUND)
4719                 return (DL_OUTSTATE);
4720 
4721         ASSERT(macinfo != NULL);
4722         ASSERT(gld->gld_sap == 0);
4723         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4724 
4725 #ifdef GLD_DEBUG
4726         if (gld_debug & GLDPROT) {
4727                 cmn_err(CE_NOTE, "gldunattach(%p, %p, PPA = %d)",
4728                     (void *)q, (void *)mp, macinfo->gldm_ppa);
4729         }
4730 #endif
4731 
4732         GLDM_LOCK(macinfo, RW_WRITER);
4733 
4734         if (gld->gld_mcast) {
4735                 for (i = 0; i < gld->gld_multicnt; i++) {
4736                         gld_mcast_t *mcast;
4737 
4738                         if ((mcast = gld->gld_mcast[i]) != NULL) {
4739                                 ASSERT(mcast->gldm_refcnt);
4740                                 gld_send_disable_multi(macinfo, mcast);
4741                         }
4742                 }
4743                 kmem_free(gld->gld_mcast,
4744                     sizeof (gld_mcast_t *) * gld->gld_multicnt);
4745                 gld->gld_mcast = NULL;
4746                 gld->gld_multicnt = 0;
4747         }
4748 
4749         /* decide if we need to turn off any promiscuity */
4750         phys_off = (gld->gld_flags & GLD_PROM_PHYS &&
4751             --mac_pvt->nprom == 0);
4752         mult_off = (gld->gld_flags & GLD_PROM_MULT &&
4753             --mac_pvt->nprom_multi == 0);
4754 
4755         if (phys_off) {
4756                 op = (mac_pvt->nprom_multi == 0) ? GLD_MAC_PROMISC_NONE :
4757                     GLD_MAC_PROMISC_MULTI;
4758         } else if (mult_off) {
4759                 op = (mac_pvt->nprom == 0) ? GLD_MAC_PROMISC_NONE :
4760                     GLD_MAC_PROMISC_NOOP;       /* phys overrides multi */
4761         }
4762 
4763         if (op != GLD_MAC_PROMISC_NOOP)
4764                 (void) (*macinfo->gldm_set_promiscuous)(macinfo, op);
4765 
4766         vlan = (gld_vlan_t *)gld->gld_vlan;
4767         if (gld->gld_flags & GLD_PROM_PHYS)
4768                 vlan->gldv_nprom--;
4769         if (gld->gld_flags & GLD_PROM_MULT)
4770                 vlan->gldv_nprom--;
4771         if (gld->gld_flags & GLD_PROM_SAP) {
4772                 vlan->gldv_nprom--;
4773                 vlan->gldv_nvlan_sap--;
4774         }
4775 
4776         gld->gld_flags &= ~(GLD_PROM_PHYS | GLD_PROM_SAP | GLD_PROM_MULT);
4777 
4778         GLDM_UNLOCK(macinfo);
4779 
4780         if (phys_off)
4781                 gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL);
4782 
4783         /*
4784          * We need to hold both locks when modifying the mac stream list
4785          * to protect findminor as well as everyone else.
4786          */
4787         mutex_enter(&glddev->gld_devlock);
4788         GLDM_LOCK(macinfo, RW_WRITER);
4789 
4790         /* disassociate this stream with its vlan and underlying mac */
4791         gldremque(gld);
4792 
4793         if (--vlan->gldv_nstreams == 0) {
4794                 gld_rem_vlan(vlan);
4795                 gld->gld_vlan = NULL;
4796         }
4797 
4798         gld->gld_mac_info = NULL;
4799         gld->gld_state = DL_UNATTACHED;
4800 
4801         /* cleanup mac layer if last vlan */
4802         if (mac_pvt->nvlan == 0) {
4803                 gld_stop_mac(macinfo);
4804                 macinfo->gldm_GLD_flags &= ~GLD_INTR_WAIT;
4805         }
4806 
4807         /* make sure no references to this gld for gld_v0_sched */
4808         if (mac_pvt->last_sched == gld)
4809                 mac_pvt->last_sched = NULL;
4810 
4811         GLDM_UNLOCK(macinfo);
4812 
4813         /* put the stream on the unattached Style 2 list */
4814         gldinsque(gld, glddev->gld_str_prev);
4815 
4816         mutex_exit(&glddev->gld_devlock);
4817 
4818         /* There will be no mp if we were called from close */
4819         if (mp) {
4820                 dlokack(q, mp, DL_DETACH_REQ);
4821         }
4822         if (gld->gld_style == DL_STYLE2)
4823                 (void) qassociate(q, -1);
4824         return (GLDE_OK);
4825 }
4826 
4827 /*
4828  * gld_enable_multi (q, mp)
4829  * Enables multicast address on the stream.  If the mac layer
4830  * isn't enabled for this address, enable at that level as well.
4831  */
4832 static int
4833 gld_enable_multi(queue_t *q, mblk_t *mp)
4834 {
4835         gld_t  *gld = (gld_t *)q->q_ptr;
4836         glddev_t *glddev;
4837         gld_mac_info_t *macinfo = gld->gld_mac_info;
4838         unsigned char *maddr;
4839         dl_enabmulti_req_t *multi;
4840         gld_mcast_t *mcast;
4841         int     i, rc;
4842         gld_mac_pvt_t *mac_pvt;
4843 
4844 #ifdef GLD_DEBUG
4845         if (gld_debug & GLDPROT) {
4846                 cmn_err(CE_NOTE, "gld_enable_multi(%p, %p)", (void *)q,
4847                     (void *)mp);
4848         }
4849 #endif
4850 
4851         if (gld->gld_state == DL_UNATTACHED)
4852                 return (DL_OUTSTATE);
4853 
4854         ASSERT(macinfo != NULL);
4855         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4856 
4857         if (macinfo->gldm_set_multicast == NULL) {
4858                 return (DL_UNSUPPORTED);
4859         }
4860 
4861         multi = (dl_enabmulti_req_t *)mp->b_rptr;
4862 
4863         if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) ||
4864             multi->dl_addr_length != macinfo->gldm_addrlen)
4865                 return (DL_BADADDR);
4866 
4867         /* request appears to be valid */
4868 
4869         glddev = mac_pvt->major_dev;
4870         ASSERT(glddev == gld->gld_device);
4871 
4872         maddr = mp->b_rptr + multi->dl_addr_offset;
4873 
4874         /*
4875          * The multicast addresses live in a per-device table, along
4876          * with a reference count.  Each stream has a table that
4877          * points to entries in the device table, with the reference
4878          * count reflecting the number of streams pointing at it.  If
4879          * this multicast address is already in the per-device table,
4880          * all we have to do is point at it.
4881          */
4882         GLDM_LOCK(macinfo, RW_WRITER);
4883 
4884         /* does this address appear in current table? */
4885         if (gld->gld_mcast == NULL) {
4886                 /* no mcast addresses -- allocate table */
4887                 gld->gld_mcast = GLD_GETSTRUCT(gld_mcast_t *,
4888                     glddev->gld_multisize);
4889                 if (gld->gld_mcast == NULL) {
4890                         GLDM_UNLOCK(macinfo);
4891                         dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
4892                         return (GLDE_OK);
4893                 }
4894                 gld->gld_multicnt = glddev->gld_multisize;
4895         } else {
4896                 for (i = 0; i < gld->gld_multicnt; i++) {
4897                         if (gld->gld_mcast[i] &&
4898                             mac_eq(gld->gld_mcast[i]->gldm_addr,
4899                             maddr, macinfo->gldm_addrlen)) {
4900                                 /* this is a match -- just succeed */
4901                                 ASSERT(gld->gld_mcast[i]->gldm_refcnt);
4902                                 GLDM_UNLOCK(macinfo);
4903                                 dlokack(q, mp, DL_ENABMULTI_REQ);
4904                                 return (GLDE_OK);
4905                         }
4906                 }
4907         }
4908 
4909         /*
4910          * it wasn't in the stream so check to see if the mac layer has it
4911          */
4912         mcast = NULL;
4913         if (mac_pvt->mcast_table == NULL) {
4914                 mac_pvt->mcast_table = GLD_GETSTRUCT(gld_mcast_t,
4915                     glddev->gld_multisize);
4916                 if (mac_pvt->mcast_table == NULL) {
4917                         GLDM_UNLOCK(macinfo);
4918                         dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
4919                         return (GLDE_OK);
4920                 }
4921         } else {
4922                 for (i = 0; i < glddev->gld_multisize; i++) {
4923                         if (mac_pvt->mcast_table[i].gldm_refcnt &&
4924                             mac_eq(mac_pvt->mcast_table[i].gldm_addr,
4925                             maddr, macinfo->gldm_addrlen)) {
4926                                 mcast = &mac_pvt->mcast_table[i];
4927                                 break;
4928                         }
4929                 }
4930         }
4931         if (mcast == NULL) {
4932                 /* not in mac layer -- find an empty mac slot to fill in */
4933                 for (i = 0; i < glddev->gld_multisize; i++) {
4934                         if (mac_pvt->mcast_table[i].gldm_refcnt == 0) {
4935                                 mcast = &mac_pvt->mcast_table[i];
4936                                 mac_copy(maddr, mcast->gldm_addr,
4937                                     macinfo->gldm_addrlen);
4938                                 break;
4939                         }
4940                 }
4941         }
4942         if (mcast == NULL) {
4943                 /* couldn't get a mac layer slot */
4944                 GLDM_UNLOCK(macinfo);
4945                 return (DL_TOOMANY);
4946         }
4947 
4948         /* now we have a mac layer slot in mcast -- get a stream slot */
4949         for (i = 0; i < gld->gld_multicnt; i++) {
4950                 if (gld->gld_mcast[i] != NULL)
4951                         continue;
4952                 /* found an empty slot */
4953                 if (!mcast->gldm_refcnt) {
4954                         /* set mcast in hardware */
4955                         unsigned char cmaddr[GLD_MAX_ADDRLEN];
4956 
4957                         ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
4958                         cmac_copy(maddr, cmaddr,
4959                             macinfo->gldm_addrlen, macinfo);
4960 
4961                         rc = (*macinfo->gldm_set_multicast)
4962                             (macinfo, cmaddr, GLD_MULTI_ENABLE);
4963                         if (rc == GLD_NOTSUPPORTED) {
4964                                 GLDM_UNLOCK(macinfo);
4965                                 return (DL_NOTSUPPORTED);
4966                         } else if (rc == GLD_NORESOURCES) {
4967                                 GLDM_UNLOCK(macinfo);
4968                                 return (DL_TOOMANY);
4969                         } else if (rc == GLD_BADARG) {
4970                                 GLDM_UNLOCK(macinfo);
4971                                 return (DL_BADADDR);
4972                         } else if (rc == GLD_RETRY) {
4973                                 /*
4974                                  * The putbq and gld_xwait must be
4975                                  * within the lock to prevent races
4976                                  * with gld_sched.
4977                                  */
4978                                 (void) putbq(q, mp);
4979                                 gld->gld_xwait = B_TRUE;
4980                                 GLDM_UNLOCK(macinfo);
4981                                 return (GLDE_RETRY);
4982                         } else if (rc != GLD_SUCCESS) {
4983                                 GLDM_UNLOCK(macinfo);
4984                                 dlerrorack(q, mp, DL_ENABMULTI_REQ,
4985                                     DL_SYSERR, EIO);
4986                                 return (GLDE_OK);
4987                         }
4988                 }
4989                 gld->gld_mcast[i] = mcast;
4990                 mcast->gldm_refcnt++;
4991                 GLDM_UNLOCK(macinfo);
4992                 dlokack(q, mp, DL_ENABMULTI_REQ);
4993                 return (GLDE_OK);
4994         }
4995 
4996         /* couldn't get a stream slot */
4997         GLDM_UNLOCK(macinfo);
4998         return (DL_TOOMANY);
4999 }
5000 
5001 
5002 /*
5003  * gld_disable_multi (q, mp)
5004  * Disable the multicast address on the stream.  If last
5005  * reference for the mac layer, disable there as well.
5006  */
5007 static int
5008 gld_disable_multi(queue_t *q, mblk_t *mp)
5009 {
5010         gld_t  *gld;
5011         gld_mac_info_t *macinfo;
5012         unsigned char *maddr;
5013         dl_disabmulti_req_t *multi;
5014         int i;
5015         gld_mcast_t *mcast;
5016 
5017 #ifdef GLD_DEBUG
5018         if (gld_debug & GLDPROT) {
5019                 cmn_err(CE_NOTE, "gld_disable_multi(%p, %p)", (void *)q,
5020                     (void *)mp);
5021         }
5022 #endif
5023 
5024         gld = (gld_t *)q->q_ptr;
5025         if (gld->gld_state == DL_UNATTACHED)
5026                 return (DL_OUTSTATE);
5027 
5028         macinfo = gld->gld_mac_info;
5029         ASSERT(macinfo != NULL);
5030         if (macinfo->gldm_set_multicast == NULL) {
5031                 return (DL_UNSUPPORTED);
5032         }
5033 
5034         multi = (dl_disabmulti_req_t *)mp->b_rptr;
5035 
5036         if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) ||
5037             multi->dl_addr_length != macinfo->gldm_addrlen)
5038                 return (DL_BADADDR);
5039 
5040         maddr = mp->b_rptr + multi->dl_addr_offset;
5041 
5042         /* request appears to be valid */
5043         /* does this address appear in current table? */
5044         GLDM_LOCK(macinfo, RW_WRITER);
5045         if (gld->gld_mcast != NULL) {
5046                 for (i = 0; i < gld->gld_multicnt; i++)
5047                         if (((mcast = gld->gld_mcast[i]) != NULL) &&
5048                             mac_eq(mcast->gldm_addr,
5049                             maddr, macinfo->gldm_addrlen)) {
5050                                 ASSERT(mcast->gldm_refcnt);
5051                                 gld_send_disable_multi(macinfo, mcast);
5052                                 gld->gld_mcast[i] = NULL;
5053                                 GLDM_UNLOCK(macinfo);
5054                                 dlokack(q, mp, DL_DISABMULTI_REQ);
5055                                 return (GLDE_OK);
5056                         }
5057         }
5058         GLDM_UNLOCK(macinfo);
5059         return (DL_NOTENAB); /* not an enabled address */
5060 }
5061 
5062 /*
5063  * gld_send_disable_multi(macinfo, mcast)
5064  * this function is used to disable a multicast address if the reference
5065  * count goes to zero. The disable request will then be forwarded to the
5066  * lower stream.
5067  */
5068 static void
5069 gld_send_disable_multi(gld_mac_info_t *macinfo, gld_mcast_t *mcast)
5070 {
5071         ASSERT(macinfo != NULL);
5072         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5073         ASSERT(mcast != NULL);
5074         ASSERT(mcast->gldm_refcnt);
5075 
5076         if (!mcast->gldm_refcnt) {
5077                 return;                 /* "cannot happen" */
5078         }
5079 
5080         if (--mcast->gldm_refcnt > 0) {
5081                 return;
5082         }
5083 
5084         /*
5085          * This must be converted from canonical form to device form.
5086          * The refcnt is now zero so we can trash the data.
5087          */
5088         if (macinfo->gldm_options & GLDOPT_CANONICAL_ADDR)
5089                 gld_bitreverse(mcast->gldm_addr, macinfo->gldm_addrlen);
5090 
5091         /* XXX Ought to check for GLD_NORESOURCES or GLD_FAILURE */
5092         (void) (*macinfo->gldm_set_multicast)
5093             (macinfo, mcast->gldm_addr, GLD_MULTI_DISABLE);
5094 }
5095 
5096 /*
5097  * gld_promisc (q, mp, req, on)
5098  *      enable or disable the use of promiscuous mode with the hardware
5099  */
5100 static int
5101 gld_promisc(queue_t *q, mblk_t *mp, t_uscalar_t req, boolean_t on)
5102 {
5103         gld_t *gld;
5104         gld_mac_info_t *macinfo;
5105         gld_mac_pvt_t *mac_pvt;
5106         gld_vlan_t *vlan;
5107         union DL_primitives *prim;
5108         int macrc = GLD_SUCCESS;
5109         int dlerr = GLDE_OK;
5110         int op = GLD_MAC_PROMISC_NOOP;
5111 
5112 #ifdef GLD_DEBUG
5113         if (gld_debug & GLDTRACE)
5114                 cmn_err(CE_NOTE, "gld_promisc(%p, %p, %d, %d)",
5115                     (void *)q, (void *)mp, req, on);
5116 #endif
5117 
5118         ASSERT(mp != NULL);
5119         prim = (union DL_primitives *)mp->b_rptr;
5120 
5121         /* XXX I think spec allows promisc in unattached state */
5122         gld = (gld_t *)q->q_ptr;
5123         if (gld->gld_state == DL_UNATTACHED)
5124                 return (DL_OUTSTATE);
5125 
5126         macinfo = gld->gld_mac_info;
5127         ASSERT(macinfo != NULL);
5128         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5129 
5130         vlan = (gld_vlan_t *)gld->gld_vlan;
5131         ASSERT(vlan != NULL);
5132 
5133         GLDM_LOCK(macinfo, RW_WRITER);
5134 
5135         /*
5136          * Work out what request (if any) has to be made to the MAC layer
5137          */
5138         if (on) {
5139                 switch (prim->promiscon_req.dl_level) {
5140                 default:
5141                         dlerr = DL_UNSUPPORTED; /* this is an error */
5142                         break;
5143 
5144                 case DL_PROMISC_PHYS:
5145                         if (mac_pvt->nprom == 0)
5146                                 op = GLD_MAC_PROMISC_PHYS;
5147                         break;
5148 
5149                 case DL_PROMISC_MULTI:
5150                         if (mac_pvt->nprom_multi == 0)
5151                                 if (mac_pvt->nprom == 0)
5152                                         op = GLD_MAC_PROMISC_MULTI;
5153                         break;
5154 
5155                 case DL_PROMISC_SAP:
5156                         /* We can do this without reference to the MAC */
5157                         break;
5158                 }
5159         } else {
5160                 switch (prim->promiscoff_req.dl_level) {
5161                 default:
5162                         dlerr = DL_UNSUPPORTED; /* this is an error */
5163                         break;
5164 
5165                 case DL_PROMISC_PHYS:
5166                         if (!(gld->gld_flags & GLD_PROM_PHYS))
5167                                 dlerr = DL_NOTENAB;
5168                         else if (mac_pvt->nprom == 1)
5169                                 if (mac_pvt->nprom_multi)
5170                                         op = GLD_MAC_PROMISC_MULTI;
5171                                 else
5172                                         op = GLD_MAC_PROMISC_NONE;
5173                         break;
5174 
5175                 case DL_PROMISC_MULTI:
5176                         if (!(gld->gld_flags & GLD_PROM_MULT))
5177                                 dlerr = DL_NOTENAB;
5178                         else if (mac_pvt->nprom_multi == 1)
5179                                 if (mac_pvt->nprom == 0)
5180                                         op = GLD_MAC_PROMISC_NONE;
5181                         break;
5182 
5183                 case DL_PROMISC_SAP:
5184                         if (!(gld->gld_flags & GLD_PROM_SAP))
5185                                 dlerr = DL_NOTENAB;
5186 
5187                         /* We can do this without reference to the MAC */
5188                         break;
5189                 }
5190         }
5191 
5192         /*
5193          * The request was invalid in some way so no need to continue.
5194          */
5195         if (dlerr != GLDE_OK) {
5196                 GLDM_UNLOCK(macinfo);
5197                 return (dlerr);
5198         }
5199 
5200         /*
5201          * Issue the request to the MAC layer, if required
5202          */
5203         if (op != GLD_MAC_PROMISC_NOOP) {
5204                 macrc = (*macinfo->gldm_set_promiscuous)(macinfo, op);
5205         }
5206 
5207         /*
5208          * On success, update the appropriate flags & refcounts
5209          */
5210         if (macrc == GLD_SUCCESS) {
5211                 if (on) {
5212                         switch (prim->promiscon_req.dl_level) {
5213                         case DL_PROMISC_PHYS:
5214                                 mac_pvt->nprom++;
5215                                 vlan->gldv_nprom++;
5216                                 gld->gld_flags |= GLD_PROM_PHYS;
5217                                 break;
5218 
5219                         case DL_PROMISC_MULTI:
5220                                 mac_pvt->nprom_multi++;
5221                                 vlan->gldv_nprom++;
5222                                 gld->gld_flags |= GLD_PROM_MULT;
5223                                 break;
5224 
5225                         case DL_PROMISC_SAP:
5226                                 gld->gld_flags |= GLD_PROM_SAP;
5227                                 vlan->gldv_nprom++;
5228                                 vlan->gldv_nvlan_sap++;
5229                                 break;
5230 
5231                         default:
5232                                 break;
5233                         }
5234                 } else {
5235                         switch (prim->promiscoff_req.dl_level) {
5236                         case DL_PROMISC_PHYS:
5237                                 mac_pvt->nprom--;
5238                                 vlan->gldv_nprom--;
5239                                 gld->gld_flags &= ~GLD_PROM_PHYS;
5240                                 break;
5241 
5242                         case DL_PROMISC_MULTI:
5243                                 mac_pvt->nprom_multi--;
5244                                 vlan->gldv_nprom--;
5245                                 gld->gld_flags &= ~GLD_PROM_MULT;
5246                                 break;
5247 
5248                         case DL_PROMISC_SAP:
5249                                 gld->gld_flags &= ~GLD_PROM_SAP;
5250                                 vlan->gldv_nvlan_sap--;
5251                                 vlan->gldv_nprom--;
5252                                 break;
5253 
5254                         default:
5255                                 break;
5256                         }
5257                 }
5258         } else if (macrc == GLD_RETRY) {
5259                 /*
5260                  * The putbq and gld_xwait must be within the lock to
5261                  * prevent races with gld_sched.
5262                  */
5263                 (void) putbq(q, mp);
5264                 gld->gld_xwait = B_TRUE;
5265         }
5266 
5267         GLDM_UNLOCK(macinfo);
5268 
5269         /*
5270          * Finally, decide how to reply.
5271          *
5272          * If <macrc> is not GLD_SUCCESS, the request was put to the MAC
5273          * layer but failed.  In such cases, we can return a DL_* error
5274          * code and let the caller send an error-ack reply upstream, or
5275          * we can send a reply here and then return GLDE_OK so that the
5276          * caller doesn't also respond.
5277          *
5278          * If physical-promiscuous mode was (successfully) switched on or
5279          * off, send a notification (DL_NOTIFY_IND) to anyone interested.
5280          */
5281         switch (macrc) {
5282         case GLD_NOTSUPPORTED:
5283                 return (DL_NOTSUPPORTED);
5284 
5285         case GLD_NORESOURCES:
5286                 dlerrorack(q, mp, req, DL_SYSERR, ENOSR);
5287                 return (GLDE_OK);
5288 
5289         case GLD_RETRY:
5290                 return (GLDE_RETRY);
5291 
5292         default:
5293                 dlerrorack(q, mp, req, DL_SYSERR, EIO);
5294                 return (GLDE_OK);
5295 
5296         case GLD_SUCCESS:
5297                 dlokack(q, mp, req);
5298                 break;
5299         }
5300 
5301         switch (op) {
5302         case GLD_MAC_PROMISC_NOOP:
5303                 break;
5304 
5305         case GLD_MAC_PROMISC_PHYS:
5306                 gld_notify_ind(macinfo, DL_NOTE_PROMISC_ON_PHYS, NULL);
5307                 break;
5308 
5309         default:
5310                 gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL);
5311                 break;
5312         }
5313 
5314         return (GLDE_OK);
5315 }
5316 
5317 /*
5318  * gld_physaddr()
5319  *      get the current or factory physical address value
5320  */
5321 static int
5322 gld_physaddr(queue_t *q, mblk_t *mp)
5323 {
5324         gld_t *gld = (gld_t *)q->q_ptr;
5325         gld_mac_info_t *macinfo;
5326         union DL_primitives *prim = (union DL_primitives *)mp->b_rptr;
5327         unsigned char addr[GLD_MAX_ADDRLEN];
5328 
5329         if (gld->gld_state == DL_UNATTACHED)
5330                 return (DL_OUTSTATE);
5331 
5332         macinfo = (gld_mac_info_t *)gld->gld_mac_info;
5333         ASSERT(macinfo != NULL);
5334         ASSERT(macinfo->gldm_addrlen <= GLD_MAX_ADDRLEN);
5335 
5336         switch (prim->physaddr_req.dl_addr_type) {
5337         case DL_FACT_PHYS_ADDR:
5338                 mac_copy((caddr_t)macinfo->gldm_vendor_addr,
5339                     (caddr_t)addr, macinfo->gldm_addrlen);
5340                 break;
5341         case DL_CURR_PHYS_ADDR:
5342                 /* make a copy so we don't hold the lock across qreply */
5343                 GLDM_LOCK(macinfo, RW_WRITER);
5344                 mac_copy((caddr_t)
5345                     ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
5346                     (caddr_t)addr, macinfo->gldm_addrlen);
5347                 GLDM_UNLOCK(macinfo);
5348                 break;
5349         default:
5350                 return (DL_BADPRIM);
5351         }
5352         dlphysaddrack(q, mp, (caddr_t)addr, macinfo->gldm_addrlen);
5353         return (GLDE_OK);
5354 }
5355 
5356 /*
5357  * gld_setaddr()
5358  *      change the hardware's physical address to a user specified value
5359  */
5360 static int
5361 gld_setaddr(queue_t *q, mblk_t *mp)
5362 {
5363         gld_t *gld = (gld_t *)q->q_ptr;
5364         gld_mac_info_t *macinfo;
5365         gld_mac_pvt_t *mac_pvt;
5366         union DL_primitives *prim = (union DL_primitives *)mp->b_rptr;
5367         unsigned char *addr;
5368         unsigned char cmaddr[GLD_MAX_ADDRLEN];
5369         int rc;
5370         gld_vlan_t *vlan;
5371 
5372         if (gld->gld_state == DL_UNATTACHED)
5373                 return (DL_OUTSTATE);
5374 
5375         vlan = (gld_vlan_t *)gld->gld_vlan;
5376         ASSERT(vlan != NULL);
5377 
5378         if (vlan->gldv_id != VLAN_VID_NONE)
5379                 return (DL_NOTSUPPORTED);
5380 
5381         macinfo = (gld_mac_info_t *)gld->gld_mac_info;
5382         ASSERT(macinfo != NULL);
5383         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5384 
5385         if (!MBLKIN(mp, prim->set_physaddr_req.dl_addr_offset,
5386             prim->set_physaddr_req.dl_addr_length) ||
5387             prim->set_physaddr_req.dl_addr_length != macinfo->gldm_addrlen)
5388                 return (DL_BADADDR);
5389 
5390         GLDM_LOCK(macinfo, RW_WRITER);
5391 
5392         /* now do the set at the hardware level */
5393         addr = mp->b_rptr + prim->set_physaddr_req.dl_addr_offset;
5394         ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
5395         cmac_copy(addr, cmaddr, macinfo->gldm_addrlen, macinfo);
5396 
5397         rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr);
5398         if (rc == GLD_SUCCESS)
5399                 mac_copy(addr, mac_pvt->curr_macaddr,
5400                     macinfo->gldm_addrlen);
5401 
5402         GLDM_UNLOCK(macinfo);
5403 
5404         switch (rc) {
5405         case GLD_SUCCESS:
5406                 break;
5407         case GLD_NOTSUPPORTED:
5408                 return (DL_NOTSUPPORTED);
5409         case GLD_BADARG:
5410                 return (DL_BADADDR);
5411         case GLD_NORESOURCES:
5412                 dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOSR);
5413                 return (GLDE_OK);
5414         default:
5415                 dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, EIO);
5416                 return (GLDE_OK);
5417         }
5418 
5419         gld_notify_ind(macinfo, DL_NOTE_PHYS_ADDR, NULL);
5420 
5421         dlokack(q, mp, DL_SET_PHYS_ADDR_REQ);
5422         return (GLDE_OK);
5423 }
5424 
5425 int
5426 gld_get_statistics(queue_t *q, mblk_t *mp)
5427 {
5428         dl_get_statistics_ack_t *dlsp;
5429         gld_t  *gld = (gld_t *)q->q_ptr;
5430         gld_mac_info_t *macinfo = gld->gld_mac_info;
5431         gld_mac_pvt_t *mac_pvt;
5432 
5433         if (gld->gld_state == DL_UNATTACHED)
5434                 return (DL_OUTSTATE);
5435 
5436         ASSERT(macinfo != NULL);
5437 
5438         mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5439         (void) gld_update_kstat(mac_pvt->kstatp, KSTAT_READ);
5440 
5441         mp = mexchange(q, mp, DL_GET_STATISTICS_ACK_SIZE +
5442             sizeof (struct gldkstats), M_PCPROTO, DL_GET_STATISTICS_ACK);
5443 
5444         if (mp == NULL)
5445                 return (GLDE_OK);       /* mexchange already sent merror */
5446 
5447         dlsp = (dl_get_statistics_ack_t *)mp->b_rptr;
5448         dlsp->dl_primitive = DL_GET_STATISTICS_ACK;
5449         dlsp->dl_stat_length = sizeof (struct gldkstats);
5450         dlsp->dl_stat_offset = DL_GET_STATISTICS_ACK_SIZE;
5451 
5452         GLDM_LOCK(macinfo, RW_WRITER);
5453         bcopy(mac_pvt->kstatp->ks_data,
5454             (mp->b_rptr + DL_GET_STATISTICS_ACK_SIZE),
5455             sizeof (struct gldkstats));
5456         GLDM_UNLOCK(macinfo);
5457 
5458         qreply(q, mp);
5459         return (GLDE_OK);
5460 }
5461 
5462 /* =================================================== */
5463 /* misc utilities, some requiring various mutexes held */
5464 /* =================================================== */
5465 
5466 /*
5467  * Initialize and start the driver.
5468  */
5469 static int
5470 gld_start_mac(gld_mac_info_t *macinfo)
5471 {
5472         int     rc;
5473         unsigned char cmaddr[GLD_MAX_ADDRLEN];
5474         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5475 
5476         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5477         ASSERT(!mac_pvt->started);
5478 
5479         rc = (*macinfo->gldm_reset)(macinfo);
5480         if (rc != GLD_SUCCESS)
5481                 return (GLD_FAILURE);
5482 
5483         /* set the addr after we reset the device */
5484         ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
5485         cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)
5486             ->curr_macaddr, cmaddr, macinfo->gldm_addrlen, macinfo);
5487 
5488         rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr);
5489         ASSERT(rc != GLD_BADARG);  /* this address was good before */
5490         if (rc != GLD_SUCCESS && rc != GLD_NOTSUPPORTED)
5491                 return (GLD_FAILURE);
5492 
5493         rc = (*macinfo->gldm_start)(macinfo);
5494         if (rc != GLD_SUCCESS)
5495                 return (GLD_FAILURE);
5496 
5497         mac_pvt->started = B_TRUE;
5498         return (GLD_SUCCESS);
5499 }
5500 
5501 /*
5502  * Stop the driver.
5503  */
5504 static void
5505 gld_stop_mac(gld_mac_info_t *macinfo)
5506 {
5507         gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5508 
5509         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5510         ASSERT(mac_pvt->started);
5511 
5512         (void) (*macinfo->gldm_stop)(macinfo);
5513 
5514         mac_pvt->started = B_FALSE;
5515 }
5516 
5517 
5518 /*
5519  * gld_set_ipq will set a pointer to the queue which is bound to the
5520  * IP sap if:
5521  * o the device type is ethernet or IPoIB.
5522  * o there is no stream in SAP promiscuous mode.
5523  * o there is exactly one stream bound to the IP sap.
5524  * o the stream is in "fastpath" mode.
5525  */
5526 static void
5527 gld_set_ipq(gld_t *gld)
5528 {
5529         gld_vlan_t      *vlan;
5530         gld_mac_info_t  *macinfo = gld->gld_mac_info;
5531         gld_t           *ip_gld = NULL;
5532         uint_t          ipq_candidates = 0;
5533         gld_t           *ipv6_gld = NULL;
5534         uint_t          ipv6q_candidates = 0;
5535 
5536         ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5537 
5538         /* The ipq code in gld_recv() is intimate with ethernet/IPoIB */
5539         if (((macinfo->gldm_type != DL_ETHER) &&
5540             (macinfo->gldm_type != DL_IB)) ||
5541             (gld_global_options & GLD_OPT_NO_IPQ))
5542                 return;
5543 
5544         vlan = (gld_vlan_t *)gld->gld_vlan;
5545         ASSERT(vlan != NULL);
5546 
5547         /* clear down any previously defined ipqs */
5548         vlan->gldv_ipq = NULL;
5549         vlan->gldv_ipv6q = NULL;
5550 
5551         /* Try to find a single stream eligible to receive IP packets */
5552         for (gld = vlan->gldv_str_next;
5553             gld != (gld_t *)&vlan->gldv_str_next; gld = gld->gld_next) {
5554                 if (gld->gld_state != DL_IDLE)
5555                         continue;       /* not eligible to receive */
5556                 if (gld->gld_flags & GLD_STR_CLOSING)
5557                         continue;       /* not eligible to receive */
5558 
5559                 if (gld->gld_sap == ETHERTYPE_IP) {
5560                         ip_gld = gld;
5561                         ipq_candidates++;
5562                 }
5563 
5564                 if (gld->gld_sap == ETHERTYPE_IPV6) {
5565                         ipv6_gld = gld;
5566                         ipv6q_candidates++;
5567                 }
5568         }
5569 
5570         if (ipq_candidates == 1) {
5571                 ASSERT(ip_gld != NULL);
5572 
5573                 if (ip_gld->gld_flags & GLD_FAST)        /* eligible for ipq */
5574                         vlan->gldv_ipq = ip_gld->gld_qptr;
5575         }
5576 
5577         if (ipv6q_candidates == 1) {
5578                 ASSERT(ipv6_gld != NULL);
5579 
5580                 if (ipv6_gld->gld_flags & GLD_FAST)      /* eligible for ipq */
5581                         vlan->gldv_ipv6q = ipv6_gld->gld_qptr;
5582         }
5583 }
5584 
5585 /*
5586  * gld_flushqueue (q)
5587  *      used by DLPI primitives that require flushing the queues.
5588  *      essentially, this is DL_UNBIND_REQ.
5589  */
5590 static void
5591 gld_flushqueue(queue_t *q)
5592 {
5593         /* flush all data in both queues */
5594         /* XXX Should these be FLUSHALL? */
5595         flushq(q, FLUSHDATA);
5596         flushq(WR(q), FLUSHDATA);
5597         /* flush all the queues upstream */
5598         (void) putctl1(q, M_FLUSH, FLUSHRW);
5599 }
5600 
5601 /*
5602  * gld_devlookup (major)
5603  * search the device table for the device with specified
5604  * major number and return a pointer to it if it exists
5605  */
5606 static glddev_t *
5607 gld_devlookup(int major)
5608 {
5609         struct glddevice *dev;
5610 
5611         ASSERT(mutex_owned(&gld_device_list.gld_devlock));
5612 
5613         for (dev = gld_device_list.gld_next;
5614             dev != &gld_device_list;
5615             dev = dev->gld_next) {
5616                 ASSERT(dev);
5617                 if (dev->gld_major == major)
5618                         return (dev);
5619         }
5620         return (NULL);
5621 }
5622 
5623 /*
5624  * gld_findminor(device)
5625  * Returns a minor number currently unused by any stream in the current
5626  * device class (major) list.
5627  */
5628 static int
5629 gld_findminor(glddev_t *device)
5630 {
5631         gld_t           *next;
5632         gld_mac_info_t  *nextmac;
5633         gld_vlan_t      *nextvlan;
5634         int             minor;
5635         int             i;
5636 
5637         ASSERT(mutex_owned(&device->gld_devlock));
5638 
5639         /* The fast way */
5640         if (device->gld_nextminor >= GLD_MIN_CLONE_MINOR &&
5641             device->gld_nextminor <= GLD_MAX_CLONE_MINOR)
5642                 return (device->gld_nextminor++);
5643 
5644         /* The steady way */
5645         for (minor = GLD_MIN_CLONE_MINOR; minor <= GLD_MAX_CLONE_MINOR;
5646             minor++) {
5647                 /* Search all unattached streams */
5648                 for (next = device->gld_str_next;
5649                     next != (gld_t *)&device->gld_str_next;
5650                     next = next->gld_next) {
5651                         if (minor == next->gld_minor)
5652                                 goto nextminor;
5653                 }
5654                 /* Search all attached streams; we don't need maclock because */
5655                 /* mac stream list is protected by devlock as well as maclock */
5656                 for (nextmac = device->gld_mac_next;
5657                     nextmac != (gld_mac_info_t *)&device->gld_mac_next;
5658                     nextmac = nextmac->gldm_next) {
5659                         gld_mac_pvt_t *pvt =
5660                             (gld_mac_pvt_t *)nextmac->gldm_mac_pvt;
5661 
5662                         if (!(nextmac->gldm_GLD_flags & GLD_MAC_READY))
5663                                 continue;       /* this one's not ready yet */
5664 
5665                         for (i = 0; i < VLAN_HASHSZ; i++) {
5666                                 for (nextvlan = pvt->vlan_hash[i];
5667                                     nextvlan != NULL;
5668                                     nextvlan = nextvlan->gldv_next) {
5669                                         for (next = nextvlan->gldv_str_next;
5670                                             next !=
5671                                             (gld_t *)&nextvlan->gldv_str_next;
5672                                             next = next->gld_next) {
5673                                                 if (minor == next->gld_minor)
5674                                                         goto nextminor;
5675                                         }
5676                                 }
5677                         }
5678                 }
5679 
5680                 return (minor);
5681 nextminor:
5682                 /* don't need to do anything */
5683                 ;
5684         }
5685         cmn_err(CE_WARN, "GLD ran out of minor numbers for %s",
5686             device->gld_name);
5687         return (0);
5688 }
5689 
5690 /*
5691  * version of insque/remque for use by this driver
5692  */
5693 struct qelem {
5694         struct qelem *q_forw;
5695         struct qelem *q_back;
5696         /* rest of structure */
5697 };
5698 
5699 static void
5700 gldinsque(void *elem, void *pred)
5701 {
5702         struct qelem *pelem = elem;
5703         struct qelem *ppred = pred;
5704         struct qelem *pnext = ppred->q_forw;
5705 
5706         pelem->q_forw = pnext;
5707         pelem->q_back = ppred;
5708         ppred->q_forw = pelem;
5709         pnext->q_back = pelem;
5710 }
5711 
5712 static void
5713 gldremque(void *arg)
5714 {
5715         struct qelem *pelem = arg;
5716         struct qelem *elem = arg;
5717 
5718         pelem->q_forw->q_back = pelem->q_back;
5719         pelem->q_back->q_forw = pelem->q_forw;
5720         elem->q_back = elem->q_forw = NULL;
5721 }
5722 
5723 static gld_vlan_t *
5724 gld_add_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5725 {
5726         gld_mac_pvt_t   *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5727         gld_vlan_t      **pp;
5728         gld_vlan_t      *p;
5729 
5730         pp = &(mac_pvt->vlan_hash[vid % VLAN_HASHSZ]);
5731         while ((p = *pp) != NULL) {
5732                 ASSERT(p->gldv_id != vid);
5733                 pp = &(p->gldv_next);
5734         }
5735 
5736         if ((p = kmem_zalloc(sizeof (gld_vlan_t), KM_NOSLEEP)) == NULL)
5737                 return (NULL);
5738 
5739         p->gldv_mac = macinfo;
5740         p->gldv_id = vid;
5741 
5742         if (vid == VLAN_VID_NONE) {
5743                 p->gldv_ptag = VLAN_VTAG_NONE;
5744                 p->gldv_stats = mac_pvt->statistics;
5745                 p->gldv_kstatp = NULL;
5746         } else {
5747                 p->gldv_ptag = GLD_MK_PTAG(VLAN_CFI_ETHER, vid);
5748                 p->gldv_stats = kmem_zalloc(sizeof (struct gld_stats),
5749                     KM_SLEEP);
5750 
5751                 if (gld_init_vlan_stats(p) != GLD_SUCCESS) {
5752                         kmem_free(p->gldv_stats, sizeof (struct gld_stats));
5753                         kmem_free(p, sizeof (gld_vlan_t));
5754                         return (NULL);
5755                 }
5756         }
5757 
5758         p->gldv_str_next = p->gldv_str_prev = (gld_t *)&p->gldv_str_next;
5759         mac_pvt->nvlan++;
5760         *pp = p;
5761 
5762         return (p);
5763 }
5764 
5765 static void
5766 gld_rem_vlan(gld_vlan_t *vlan)
5767 {
5768         gld_mac_info_t  *macinfo = vlan->gldv_mac;
5769         gld_mac_pvt_t   *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5770         gld_vlan_t      **pp;
5771         gld_vlan_t      *p;
5772 
5773         pp = &(mac_pvt->vlan_hash[vlan->gldv_id % VLAN_HASHSZ]);
5774         while ((p = *pp) != NULL) {
5775                 if (p->gldv_id == vlan->gldv_id)
5776                         break;
5777                 pp = &(p->gldv_next);
5778         }
5779         ASSERT(p != NULL);
5780 
5781         *pp = p->gldv_next;
5782         mac_pvt->nvlan--;
5783         if (p->gldv_id != VLAN_VID_NONE) {
5784                 ASSERT(p->gldv_kstatp != NULL);
5785                 kstat_delete(p->gldv_kstatp);
5786                 kmem_free(p->gldv_stats, sizeof (struct gld_stats));
5787         }
5788         kmem_free(p, sizeof (gld_vlan_t));
5789 }
5790 
5791 gld_vlan_t *
5792 gld_find_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5793 {
5794         gld_mac_pvt_t   *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5795         gld_vlan_t      *p;
5796 
5797         p = mac_pvt->vlan_hash[vid % VLAN_HASHSZ];
5798         while (p != NULL) {
5799                 if (p->gldv_id == vid)
5800                         return (p);
5801                 p = p->gldv_next;
5802         }
5803         return (NULL);
5804 }
5805 
5806 gld_vlan_t *
5807 gld_get_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5808 {
5809         gld_vlan_t      *vlan;
5810 
5811         if ((vlan = gld_find_vlan(macinfo, vid)) == NULL)
5812                 vlan = gld_add_vlan(macinfo, vid);
5813 
5814         return (vlan);
5815 }
5816 
5817 /*
5818  * gld_bitrevcopy()
5819  * This is essentially bcopy, with the ability to bit reverse the
5820  * the source bytes. The MAC addresses bytes as transmitted by FDDI
5821  * interfaces are bit reversed.
5822  */
5823 void
5824 gld_bitrevcopy(caddr_t src, caddr_t target, size_t n)
5825 {
5826         while (n--)
5827                 *target++ = bit_rev[(uchar_t)*src++];
5828 }
5829 
5830 /*
5831  * gld_bitreverse()
5832  * Convert the bit order by swaping all the bits, using a
5833  * lookup table.
5834  */
5835 void
5836 gld_bitreverse(uchar_t *rptr, size_t n)
5837 {
5838         while (n--) {
5839                 *rptr = bit_rev[*rptr];
5840                 rptr++;
5841         }
5842 }
5843 
5844 char *
5845 gld_macaddr_sprintf(char *etherbuf, unsigned char *ap, int len)
5846 {
5847         int i;
5848         char *cp = etherbuf;
5849         static char digits[] = "0123456789abcdef";
5850 
5851         for (i = 0; i < len; i++) {
5852                 *cp++ = digits[*ap >> 4];
5853                 *cp++ = digits[*ap++ & 0xf];
5854                 *cp++ = ':';
5855         }
5856         *--cp = 0;
5857         return (etherbuf);
5858 }
5859 
5860 #ifdef GLD_DEBUG
5861 static void
5862 gld_check_assertions()
5863 {
5864         glddev_t        *dev;
5865         gld_mac_info_t  *mac;
5866         gld_t           *str;
5867         gld_vlan_t      *vlan;
5868         int             i;
5869 
5870         mutex_enter(&gld_device_list.gld_devlock);
5871 
5872         for (dev = gld_device_list.gld_next;
5873             dev != (glddev_t *)&gld_device_list.gld_next;
5874             dev = dev->gld_next) {
5875                 mutex_enter(&dev->gld_devlock);
5876                 ASSERT(dev->gld_broadcast != NULL);
5877                 for (str = dev->gld_str_next;
5878                     str != (gld_t *)&dev->gld_str_next;
5879                     str = str->gld_next) {
5880                         ASSERT(str->gld_device == dev);
5881                         ASSERT(str->gld_mac_info == NULL);
5882                         ASSERT(str->gld_qptr != NULL);
5883                         ASSERT(str->gld_minor >= GLD_MIN_CLONE_MINOR);
5884                         ASSERT(str->gld_multicnt == 0);
5885                         ASSERT(str->gld_mcast == NULL);
5886                         ASSERT(!(str->gld_flags &
5887                             (GLD_PROM_PHYS|GLD_PROM_MULT|GLD_PROM_SAP)));
5888                         ASSERT(str->gld_sap == 0);
5889                         ASSERT(str->gld_state == DL_UNATTACHED);
5890                 }
5891                 for (mac = dev->gld_mac_next;
5892                     mac != (gld_mac_info_t *)&dev->gld_mac_next;
5893                     mac = mac->gldm_next) {
5894                         int nvlan = 0;
5895                         gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
5896 
5897                         if (!(mac->gldm_GLD_flags & GLD_MAC_READY))
5898                                 continue;       /* this one's not ready yet */
5899 
5900                         GLDM_LOCK(mac, RW_WRITER);
5901                         ASSERT(mac->gldm_devinfo != NULL);
5902                         ASSERT(mac->gldm_mac_pvt != NULL);
5903                         ASSERT(pvt->interfacep != NULL);
5904                         ASSERT(pvt->kstatp != NULL);
5905                         ASSERT(pvt->statistics != NULL);
5906                         ASSERT(pvt->major_dev == dev);
5907 
5908                         for (i = 0; i < VLAN_HASHSZ; i++) {
5909                                 for (vlan = pvt->vlan_hash[i];
5910                                     vlan != NULL; vlan = vlan->gldv_next) {
5911                                         int nstr = 0;
5912 
5913                                         ASSERT(vlan->gldv_mac == mac);
5914 
5915                                         for (str = vlan->gldv_str_next;
5916                                             str !=
5917                                             (gld_t *)&vlan->gldv_str_next;
5918                                             str = str->gld_next) {
5919                                                 ASSERT(str->gld_device == dev);
5920                                                 ASSERT(str->gld_mac_info ==
5921                                                     mac);
5922                                                 ASSERT(str->gld_qptr != NULL);
5923                                                 ASSERT(str->gld_minor >=
5924                                                     GLD_MIN_CLONE_MINOR);
5925                                                 ASSERT(
5926                                                     str->gld_multicnt == 0 ||
5927                                                     str->gld_mcast);
5928                                                 nstr++;
5929                                         }
5930                                         ASSERT(vlan->gldv_nstreams == nstr);
5931                                         nvlan++;
5932                                 }
5933                         }
5934                         ASSERT(pvt->nvlan == nvlan);
5935                         GLDM_UNLOCK(mac);
5936                 }
5937                 mutex_exit(&dev->gld_devlock);
5938         }
5939         mutex_exit(&gld_device_list.gld_devlock);
5940 }
5941 #endif