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