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