xref: /titanic_44/usr/src/uts/common/io/gld.c (revision 734b6a94890be549309b21156f8ed6d4561cac51)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * gld - Generic LAN Driver Version 2, PSARC/1997/382
30  *
31  * This is a utility module that provides generic facilities for
32  * LAN	drivers.  The DLPI protocol and most STREAMS interfaces
33  * are handled here.
34  *
35  * It no longer provides compatibility with drivers
36  * implemented according to the GLD v0 documentation published
37  * in 1993. (See PSARC 2003/728)
38  */
39 
40 
41 #include <sys/types.h>
42 #include <sys/errno.h>
43 #include <sys/stropts.h>
44 #include <sys/stream.h>
45 #include <sys/kmem.h>
46 #include <sys/stat.h>
47 #include <sys/modctl.h>
48 #include <sys/kstat.h>
49 #include <sys/debug.h>
50 #include <sys/note.h>
51 #include <sys/sysmacros.h>
52 
53 #include <sys/byteorder.h>
54 #include <sys/strsun.h>
55 #include <sys/strsubr.h>
56 #include <sys/dlpi.h>
57 #include <sys/pattr.h>
58 #include <sys/ethernet.h>
59 #include <sys/ib/clients/ibd/ibd.h>
60 #include <sys/policy.h>
61 #include <sys/atomic.h>
62 
63 #include <sys/multidata.h>
64 #include <sys/gld.h>
65 #include <sys/gldpriv.h>
66 
67 #include <sys/ddi.h>
68 #include <sys/sunddi.h>
69 
70 /*
71  * Macro to atomically increment counters of type uint32_t, uint64_t
72  * and ulong_t.
73  */
74 #define	BUMP(stat, delta)	do {				\
75 	_NOTE(CONSTANTCONDITION)				\
76 	if (sizeof (stat) == sizeof (uint32_t))	{		\
77 		atomic_add_32((uint32_t *)&stat, delta);	\
78 	_NOTE(CONSTANTCONDITION)				\
79 	} else if (sizeof (stat) == sizeof (uint64_t)) {	\
80 		atomic_add_64((uint64_t *)&stat, delta);	\
81 	}							\
82 	_NOTE(CONSTANTCONDITION)				\
83 } while (0)
84 
85 #define	UPDATE_STATS(vlan, pktinfo, number)	{		\
86 	if ((pktinfo).isBroadcast)				\
87 		(vlan)->gldv_stats->glds_brdcstxmt += (number);	\
88 	else if ((pktinfo).isMulticast)				\
89 		(vlan)->gldv_stats->glds_multixmt += (number);	\
90 	(vlan)->gldv_stats->glds_bytexmt64 += (pktinfo).pktLen;	\
91 	(vlan)->gldv_stats->glds_pktxmt64 += (number);		\
92 }
93 
94 #ifdef GLD_DEBUG
95 int gld_debug = GLDERRS;
96 #endif
97 
98 /* called from gld_register */
99 static int gld_initstats(gld_mac_info_t *);
100 
101 /* called from kstat mechanism, and from wsrv's get_statistics */
102 static int gld_update_kstat(kstat_t *, int);
103 
104 /* statistics for additional vlans */
105 static int gld_init_vlan_stats(gld_vlan_t *);
106 static int gld_update_vlan_kstat(kstat_t *, int);
107 
108 /* called from gld_getinfo */
109 static dev_info_t *gld_finddevinfo(dev_t);
110 
111 /* called from wput, wsrv, unidata, and v0_sched to send a packet */
112 /* also from the source routing stuff for sending RDE protocol packets */
113 static int gld_start(queue_t *, mblk_t *, int, uint32_t);
114 static int gld_start_mdt(queue_t *, mblk_t *, int);
115 
116 /* called from gld_start[_mdt] to loopback packet(s) in promiscuous mode */
117 static void gld_precv(gld_mac_info_t *, gld_vlan_t *, mblk_t *);
118 static void gld_precv_mdt(gld_mac_info_t *, gld_vlan_t *, mblk_t *,
119     pdesc_t *, pktinfo_t *);
120 
121 /* receive group: called from gld_recv and gld_precv* with maclock held */
122 static void gld_sendup(gld_mac_info_t *, gld_vlan_t *, pktinfo_t *, mblk_t *,
123     int (*)());
124 static int gld_accept(gld_t *, pktinfo_t *);
125 static int gld_mcmatch(gld_t *, pktinfo_t *);
126 static int gld_multicast(unsigned char *, gld_t *);
127 static int gld_paccept(gld_t *, pktinfo_t *);
128 static void gld_passon(gld_t *, mblk_t *, pktinfo_t *,
129     void (*)(queue_t *, mblk_t *));
130 static mblk_t *gld_addudind(gld_t *, mblk_t *, pktinfo_t *);
131 
132 /* wsrv group: called from wsrv, single threaded per queue */
133 static int gld_ioctl(queue_t *, mblk_t *);
134 static void gld_fastpath(gld_t *, queue_t *, mblk_t *);
135 static int gld_cmds(queue_t *, mblk_t *);
136 static mblk_t *gld_bindack(queue_t *, mblk_t *);
137 static int gld_notify_req(queue_t *, mblk_t *);
138 static int gld_udqos(queue_t *, mblk_t *);
139 static int gld_bind(queue_t *, mblk_t *);
140 static int gld_unbind(queue_t *, mblk_t *);
141 static int gld_inforeq(queue_t *, mblk_t *);
142 static int gld_unitdata(queue_t *, mblk_t *);
143 static int gldattach(queue_t *, mblk_t *);
144 static int gldunattach(queue_t *, mblk_t *);
145 static int gld_enable_multi(queue_t *, mblk_t *);
146 static int gld_disable_multi(queue_t *, mblk_t *);
147 static void gld_send_disable_multi(gld_mac_info_t *, gld_mcast_t *);
148 static int gld_promisc(queue_t *, mblk_t *, t_uscalar_t, boolean_t);
149 static int gld_physaddr(queue_t *, mblk_t *);
150 static int gld_setaddr(queue_t *, mblk_t *);
151 static int gld_get_statistics(queue_t *, mblk_t *);
152 static int gld_cap(queue_t *, mblk_t *);
153 static int gld_cap_ack(queue_t *, mblk_t *);
154 static int gld_cap_enable(queue_t *, mblk_t *);
155 
156 /* misc utilities, some requiring various mutexes held */
157 static int gld_start_mac(gld_mac_info_t *);
158 static void gld_stop_mac(gld_mac_info_t *);
159 static void gld_set_ipq(gld_t *);
160 static void gld_flushqueue(queue_t *);
161 static glddev_t *gld_devlookup(int);
162 static int gld_findminor(glddev_t *);
163 static void gldinsque(void *, void *);
164 static void gldremque(void *);
165 void gld_bitrevcopy(caddr_t, caddr_t, size_t);
166 void gld_bitreverse(uchar_t *, size_t);
167 char *gld_macaddr_sprintf(char *, unsigned char *, int);
168 static gld_vlan_t *gld_add_vlan(gld_mac_info_t *, uint32_t vid);
169 static void gld_rem_vlan(gld_vlan_t *);
170 gld_vlan_t *gld_find_vlan(gld_mac_info_t *, uint32_t);
171 gld_vlan_t *gld_get_vlan(gld_mac_info_t *, uint32_t);
172 
173 #ifdef GLD_DEBUG
174 static void gld_check_assertions(void);
175 extern void gld_sr_dump(gld_mac_info_t *);
176 #endif
177 
178 /*
179  * Allocate and zero-out "number" structures each of type "structure" in
180  * kernel memory.
181  */
182 #define	GETSTRUCT(structure, number)   \
183 	(kmem_zalloc((uint_t)(sizeof (structure) * (number)), KM_NOSLEEP))
184 
185 #define	abs(a) ((a) < 0 ? -(a) : a)
186 
187 uint32_t gld_global_options = GLD_OPT_NO_ETHRXSNAP;
188 
189 /*
190  * VLANs are only supported on ethernet devices that manipulate VLAN headers
191  * themselves.
192  */
193 #define	VLAN_CAPABLE(macinfo) \
194 	((macinfo)->gldm_type == DL_ETHER && \
195 	(macinfo)->gldm_send_tagged != NULL)
196 
197 /*
198  * The set of notifications generatable by GLD itself, the additional
199  * set that can be generated if the MAC driver provide the link-state
200  * tracking callback capability, and the set supported by the GLD
201  * notification code below.
202  *
203  * PLEASE keep these in sync with what the code actually does!
204  */
205 static const uint32_t gld_internal_notes =	DL_NOTE_PROMISC_ON_PHYS |
206 						DL_NOTE_PROMISC_OFF_PHYS |
207 						DL_NOTE_PHYS_ADDR;
208 static const uint32_t gld_linkstate_notes =	DL_NOTE_LINK_DOWN |
209 						DL_NOTE_LINK_UP |
210 						DL_NOTE_SPEED;
211 static const uint32_t gld_supported_notes =	DL_NOTE_PROMISC_ON_PHYS |
212 						DL_NOTE_PROMISC_OFF_PHYS |
213 						DL_NOTE_PHYS_ADDR |
214 						DL_NOTE_LINK_DOWN |
215 						DL_NOTE_LINK_UP |
216 						DL_NOTE_SPEED;
217 
218 /* Media must correspond to #defines in gld.h */
219 static char *gld_media[] = {
220 	"unknown",	/* GLDM_UNKNOWN - driver cannot determine media */
221 	"aui",		/* GLDM_AUI */
222 	"bnc",		/* GLDM_BNC */
223 	"twpair",	/* GLDM_TP */
224 	"fiber",	/* GLDM_FIBER */
225 	"100baseT",	/* GLDM_100BT */
226 	"100vgAnyLan",	/* GLDM_VGANYLAN */
227 	"10baseT",	/* GLDM_10BT */
228 	"ring4",	/* GLDM_RING4 */
229 	"ring16",	/* GLDM_RING16 */
230 	"PHY/MII",	/* GLDM_PHYMII */
231 	"100baseTX",	/* GLDM_100BTX */
232 	"100baseT4",	/* GLDM_100BT4 */
233 	"unknown",	/* skip */
234 	"ipib",		/* GLDM_IB */
235 };
236 
237 /* Must correspond to #defines in gld.h */
238 static char *gld_duplex[] = {
239 	"unknown",	/* GLD_DUPLEX_UNKNOWN - not known or not applicable */
240 	"half",		/* GLD_DUPLEX_HALF */
241 	"full"		/* GLD_DUPLEX_FULL */
242 };
243 
244 extern int gld_interpret_ether(gld_mac_info_t *, mblk_t *, pktinfo_t *, int);
245 extern int gld_interpret_fddi(gld_mac_info_t *, mblk_t *, pktinfo_t *, int);
246 extern int gld_interpret_tr(gld_mac_info_t *, mblk_t *, pktinfo_t *, int);
247 extern int gld_interpret_ib(gld_mac_info_t *, mblk_t *, pktinfo_t *, int);
248 extern void gld_interpret_mdt_ib(gld_mac_info_t *, mblk_t *, pdescinfo_t *,
249     pktinfo_t *, int);
250 
251 extern mblk_t *gld_fastpath_ether(gld_t *, mblk_t *);
252 extern mblk_t *gld_fastpath_fddi(gld_t *, mblk_t *);
253 extern mblk_t *gld_fastpath_tr(gld_t *, mblk_t *);
254 extern mblk_t *gld_fastpath_ib(gld_t *, mblk_t *);
255 
256 extern mblk_t *gld_unitdata_ether(gld_t *, mblk_t *);
257 extern mblk_t *gld_unitdata_fddi(gld_t *, mblk_t *);
258 extern mblk_t *gld_unitdata_tr(gld_t *, mblk_t *);
259 extern mblk_t *gld_unitdata_ib(gld_t *, mblk_t *);
260 
261 extern void gld_init_ether(gld_mac_info_t *);
262 extern void gld_init_fddi(gld_mac_info_t *);
263 extern void gld_init_tr(gld_mac_info_t *);
264 extern void gld_init_ib(gld_mac_info_t *);
265 
266 extern void gld_uninit_ether(gld_mac_info_t *);
267 extern void gld_uninit_fddi(gld_mac_info_t *);
268 extern void gld_uninit_tr(gld_mac_info_t *);
269 extern void gld_uninit_ib(gld_mac_info_t *);
270 
271 /*
272  * Interface types currently supported by GLD.
273  * If you add new types, you must check all "XXX" strings in the GLD source
274  * for implementation issues that may affect the support of your new type.
275  * In particular, any type with gldm_addrlen > 6, or gldm_saplen != -2, will
276  * require generalizing this GLD source to handle the new cases.  In other
277  * words there are assumptions built into the code in a few places that must
278  * be fixed.  Be sure to turn on DEBUG/ASSERT code when testing a new type.
279  */
280 static gld_interface_t interfaces[] = {
281 
282 	/* Ethernet Bus */
283 	{
284 		DL_ETHER,
285 		(uint_t)-1,
286 		sizeof (struct ether_mac_frm),
287 		gld_interpret_ether,
288 		NULL,
289 		gld_fastpath_ether,
290 		gld_unitdata_ether,
291 		gld_init_ether,
292 		gld_uninit_ether,
293 		"ether"
294 	},
295 
296 	/* Fiber Distributed data interface */
297 	{
298 		DL_FDDI,
299 		4352,
300 		sizeof (struct fddi_mac_frm),
301 		gld_interpret_fddi,
302 		NULL,
303 		gld_fastpath_fddi,
304 		gld_unitdata_fddi,
305 		gld_init_fddi,
306 		gld_uninit_fddi,
307 		"fddi"
308 	},
309 
310 	/* Token Ring interface */
311 	{
312 		DL_TPR,
313 		17914,
314 		-1,			/* variable header size */
315 		gld_interpret_tr,
316 		NULL,
317 		gld_fastpath_tr,
318 		gld_unitdata_tr,
319 		gld_init_tr,
320 		gld_uninit_tr,
321 		"tpr"
322 	},
323 
324 	/* Infiniband */
325 	{
326 		DL_IB,
327 		4092,
328 		sizeof (struct ipoib_header),
329 		gld_interpret_ib,
330 		gld_interpret_mdt_ib,
331 		gld_fastpath_ib,
332 		gld_unitdata_ib,
333 		gld_init_ib,
334 		gld_uninit_ib,
335 		"ipib"
336 	},
337 };
338 
339 /*
340  * bit reversal lookup table.
341  */
342 static	uchar_t bit_rev[] = {
343 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
344 	0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
345 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
346 	0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
347 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
348 	0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
349 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
350 	0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
351 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
352 	0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
353 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
354 	0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
355 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
356 	0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
357 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
358 	0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
359 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
360 	0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
361 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
362 	0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
363 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
364 	0x3f, 0xbf, 0x7f, 0xff,
365 };
366 
367 /*
368  * User priorities, mapped from b_band.
369  */
370 static uint32_t user_priority[] = {
371 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
372 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
374 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
375 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
376 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
377 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
378 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
379 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
380 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
381 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
382 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
383 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
384 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
385 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
386 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
387 };
388 
389 #define	UPRI(gld, band)	((band != 0) ? user_priority[(band)] : (gld)->gld_upri)
390 
391 static struct glddevice gld_device_list;  /* Per-system root of GLD tables */
392 
393 /*
394  * Module linkage information for the kernel.
395  */
396 
397 static struct modldrv modlmisc = {
398 	&mod_miscops,		/* Type of module - a utility provider */
399 	"Generic LAN Driver (" GLD_VERSION_STRING ") %I%"
400 #ifdef GLD_DEBUG
401 	" DEBUG"
402 #endif
403 };
404 
405 static struct modlinkage modlinkage = {
406 	MODREV_1, &modlmisc, NULL
407 };
408 
409 int
410 _init(void)
411 {
412 	int e;
413 
414 	/* initialize gld_device_list mutex */
415 	mutex_init(&gld_device_list.gld_devlock, NULL, MUTEX_DRIVER, NULL);
416 
417 	/* initialize device driver (per-major) list */
418 	gld_device_list.gld_next =
419 	    gld_device_list.gld_prev = &gld_device_list;
420 
421 	if ((e = mod_install(&modlinkage)) != 0)
422 		mutex_destroy(&gld_device_list.gld_devlock);
423 
424 	return (e);
425 }
426 
427 int
428 _fini(void)
429 {
430 	int e;
431 
432 	if ((e = mod_remove(&modlinkage)) != 0)
433 		return (e);
434 
435 	ASSERT(gld_device_list.gld_next ==
436 	    (glddev_t *)&gld_device_list.gld_next);
437 	ASSERT(gld_device_list.gld_prev ==
438 	    (glddev_t *)&gld_device_list.gld_next);
439 	mutex_destroy(&gld_device_list.gld_devlock);
440 
441 	return (e);
442 }
443 
444 int
445 _info(struct modinfo *modinfop)
446 {
447 	return (mod_info(&modlinkage, modinfop));
448 }
449 
450 /*
451  * GLD service routines
452  */
453 
454 /* So this gld binary maybe can be forward compatible with future v2 drivers */
455 #define	GLD_MAC_RESERVED (16 * sizeof (caddr_t))
456 
457 /*ARGSUSED*/
458 gld_mac_info_t *
459 gld_mac_alloc(dev_info_t *devinfo)
460 {
461 	gld_mac_info_t *macinfo;
462 
463 	macinfo = kmem_zalloc(sizeof (gld_mac_info_t) + GLD_MAC_RESERVED,
464 	    KM_SLEEP);
465 
466 	/*
467 	 * The setting of gldm_driver_version will not be documented or allowed
468 	 * until a future release.
469 	 */
470 	macinfo->gldm_driver_version = GLD_VERSION_200;
471 
472 	/*
473 	 * GLD's version.  This also is undocumented for now, but will be
474 	 * available if needed in the future.
475 	 */
476 	macinfo->gldm_GLD_version = GLD_VERSION;
477 
478 	return (macinfo);
479 }
480 
481 /*
482  * gld_mac_free must be called after the driver has removed interrupts
483  * and completely stopped calling gld_recv() and gld_sched().  At that
484  * point the interrupt routine is guaranteed by the system to have been
485  * exited and the maclock is no longer needed.  Of course, it is
486  * expected (required) that (assuming gld_register() succeeded),
487  * gld_unregister() was called before gld_mac_free().
488  */
489 void
490 gld_mac_free(gld_mac_info_t *macinfo)
491 {
492 	ASSERT(macinfo);
493 	ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
494 
495 	/*
496 	 * Assert that if we made it through gld_register, then we must
497 	 * have unregistered.
498 	 */
499 	ASSERT(!GLDM_LOCK_INITED(macinfo) ||
500 	    (macinfo->gldm_GLD_flags & GLD_UNREGISTERED));
501 
502 	GLDM_LOCK_DESTROY(macinfo);
503 
504 	kmem_free(macinfo, sizeof (gld_mac_info_t) + GLD_MAC_RESERVED);
505 }
506 
507 /*
508  * gld_register -- called once per device instance (PPA)
509  *
510  * During its attach routine, a real device driver will register with GLD
511  * so that later opens and dl_attach_reqs will work.  The arguments are the
512  * devinfo pointer, the device name, and a macinfo structure describing the
513  * physical device instance.
514  */
515 int
516 gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo)
517 {
518 	int mediatype;
519 	int major = ddi_name_to_major(devname), i;
520 	glddev_t *glddev;
521 	gld_mac_pvt_t *mac_pvt;
522 	char minordev[32];
523 	char pbuf[3*GLD_MAX_ADDRLEN];
524 	gld_interface_t *ifp;
525 
526 	ASSERT(devinfo != NULL);
527 	ASSERT(macinfo != NULL);
528 
529 	if (macinfo->gldm_driver_version != GLD_VERSION)
530 		return (DDI_FAILURE);
531 
532 	mediatype = macinfo->gldm_type;
533 
534 	/*
535 	 * Entry points should be ready for us.
536 	 * ioctl is optional.
537 	 * set_multicast and get_stats are optional in v0.
538 	 * intr is only required if you add an interrupt.
539 	 */
540 	ASSERT(macinfo->gldm_reset != NULL);
541 	ASSERT(macinfo->gldm_start != NULL);
542 	ASSERT(macinfo->gldm_stop != NULL);
543 	ASSERT(macinfo->gldm_set_mac_addr != NULL);
544 	ASSERT(macinfo->gldm_set_promiscuous != NULL);
545 	ASSERT(macinfo->gldm_send != NULL);
546 
547 	ASSERT(macinfo->gldm_maxpkt >= macinfo->gldm_minpkt);
548 	ASSERT(macinfo->gldm_GLD_version == GLD_VERSION);
549 	ASSERT(macinfo->gldm_broadcast_addr != NULL);
550 	ASSERT(macinfo->gldm_vendor_addr != NULL);
551 	ASSERT(macinfo->gldm_ident != NULL);
552 
553 	if (macinfo->gldm_addrlen > GLD_MAX_ADDRLEN) {
554 		cmn_err(CE_WARN, "GLD: %s driver gldm_addrlen %d > %d not sup"
555 		    "ported", devname, macinfo->gldm_addrlen, GLD_MAX_ADDRLEN);
556 		return (DDI_FAILURE);
557 	}
558 
559 	/*
560 	 * GLD only functions properly with saplen == -2
561 	 */
562 	if (macinfo->gldm_saplen != -2) {
563 		cmn_err(CE_WARN, "GLD: %s driver gldm_saplen %d != -2 "
564 		    "not supported", devname, macinfo->gldm_saplen);
565 		return (DDI_FAILURE);
566 	}
567 
568 	/* see gld_rsrv() */
569 	if (ddi_getprop(DDI_DEV_T_NONE, devinfo, 0, "fast_recv", 0))
570 		macinfo->gldm_options |= GLDOPT_FAST_RECV;
571 
572 	mutex_enter(&gld_device_list.gld_devlock);
573 	glddev = gld_devlookup(major);
574 
575 	/*
576 	 *  Allocate per-driver (major) data structure if necessary
577 	 */
578 	if (glddev == NULL) {
579 		/* first occurrence of this device name (major number) */
580 		glddev = GETSTRUCT(glddev_t, 1);
581 		if (glddev == NULL) {
582 			mutex_exit(&gld_device_list.gld_devlock);
583 			return (DDI_FAILURE);
584 		}
585 		(void) strncpy(glddev->gld_name, devname,
586 		    sizeof (glddev->gld_name) - 1);
587 		glddev->gld_major = major;
588 		glddev->gld_nextminor = GLD_MIN_CLONE_MINOR;
589 		glddev->gld_mac_next = glddev->gld_mac_prev =
590 			(gld_mac_info_t *)&glddev->gld_mac_next;
591 		glddev->gld_str_next = glddev->gld_str_prev =
592 			(gld_t *)&glddev->gld_str_next;
593 		mutex_init(&glddev->gld_devlock, NULL, MUTEX_DRIVER, NULL);
594 
595 		/* allow increase of number of supported multicast addrs */
596 		glddev->gld_multisize = ddi_getprop(DDI_DEV_T_NONE,
597 		    devinfo, 0, "multisize", GLD_MAX_MULTICAST);
598 
599 		/*
600 		 * Optionally restrict DLPI provider style
601 		 *
602 		 * -1 - don't create style 1 nodes
603 		 * -2 - don't create style 2 nodes
604 		 */
605 		glddev->gld_styles = ddi_getprop(DDI_DEV_T_NONE, devinfo, 0,
606 		    "gld-provider-styles", 0);
607 
608 		/* Stuff that's needed before any PPA gets attached */
609 		glddev->gld_type = macinfo->gldm_type;
610 		glddev->gld_minsdu = macinfo->gldm_minpkt;
611 		glddev->gld_saplen = macinfo->gldm_saplen;
612 		glddev->gld_addrlen = macinfo->gldm_addrlen;
613 		glddev->gld_broadcast = kmem_zalloc(macinfo->gldm_addrlen,
614 		    KM_SLEEP);
615 		bcopy(macinfo->gldm_broadcast_addr,
616 		    glddev->gld_broadcast, macinfo->gldm_addrlen);
617 		glddev->gld_maxsdu = macinfo->gldm_maxpkt;
618 		gldinsque(glddev, gld_device_list.gld_prev);
619 	}
620 	glddev->gld_ndevice++;
621 	/* Now glddev can't go away until we unregister this mac (or fail) */
622 	mutex_exit(&gld_device_list.gld_devlock);
623 
624 	/*
625 	 *  Per-instance initialization
626 	 */
627 
628 	/*
629 	 * Initialize per-mac structure that is private to GLD.
630 	 * Set up interface pointer. These are device class specific pointers
631 	 * used to handle FDDI/TR/ETHER/IPoIB specific packets.
632 	 */
633 	for (i = 0; i < sizeof (interfaces)/sizeof (*interfaces); i++) {
634 		if (mediatype != interfaces[i].mac_type)
635 			continue;
636 
637 		macinfo->gldm_mac_pvt = kmem_zalloc(sizeof (gld_mac_pvt_t),
638 		    KM_SLEEP);
639 		((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep = ifp =
640 		    &interfaces[i];
641 		break;
642 	}
643 
644 	if (ifp == NULL) {
645 		cmn_err(CE_WARN, "GLD: this version does not support %s driver "
646 		    "of type %d", devname, mediatype);
647 		goto failure;
648 	}
649 
650 	/*
651 	 * Driver can only register MTU within legal media range.
652 	 */
653 	if (macinfo->gldm_maxpkt > ifp->mtu_size) {
654 		cmn_err(CE_WARN, "GLD: oversize MTU is specified by driver %s",
655 		    devname);
656 		goto failure;
657 	}
658 
659 	/*
660 	 * For now, only Infiniband drivers can use MDT. Do not add
661 	 * support for Ethernet, FDDI or TR.
662 	 */
663 	if (macinfo->gldm_mdt_pre != NULL) {
664 		if (mediatype != DL_IB) {
665 			cmn_err(CE_WARN, "GLD: MDT not supported for %s "
666 			    "driver of type %d", devname, mediatype);
667 			goto failure;
668 		}
669 
670 		/*
671 		 * Validate entry points.
672 		 */
673 		if ((macinfo->gldm_mdt_send == NULL) ||
674 		    (macinfo->gldm_mdt_post == NULL)) {
675 			cmn_err(CE_WARN, "GLD: invalid MDT entry points for "
676 			    "%s driver of type %d", devname, mediatype);
677 			goto failure;
678 		}
679 		macinfo->gldm_options |= GLDOPT_MDT;
680 	}
681 
682 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
683 	mac_pvt->major_dev = glddev;
684 
685 	mac_pvt->curr_macaddr = kmem_zalloc(macinfo->gldm_addrlen, KM_SLEEP);
686 	/*
687 	 * XXX Do bit-reversed devices store gldm_vendor in canonical
688 	 * format or in wire format?  Also gldm_broadcast.  For now
689 	 * we are assuming canonical, but I'm not sure that makes the
690 	 * most sense for ease of driver implementation.
691 	 */
692 	bcopy(macinfo->gldm_vendor_addr, mac_pvt->curr_macaddr,
693 	    macinfo->gldm_addrlen);
694 	mac_pvt->statistics = kmem_zalloc(sizeof (struct gld_stats), KM_SLEEP);
695 
696 	/*
697 	 * The available set of notifications is those generatable by GLD
698 	 * itself, plus those corresponding to the capabilities of the MAC
699 	 * driver, intersected with those supported by gld_notify_ind() above.
700 	 */
701 	mac_pvt->notifications = gld_internal_notes;
702 	if (macinfo->gldm_capabilities & GLD_CAP_LINKSTATE)
703 		mac_pvt->notifications |= gld_linkstate_notes;
704 	mac_pvt->notifications &= gld_supported_notes;
705 
706 	GLDM_LOCK_INIT(macinfo);
707 
708 	ddi_set_driver_private(devinfo, macinfo);
709 
710 	/*
711 	 * Now atomically get a PPA and put ourselves on the mac list.
712 	 */
713 	mutex_enter(&glddev->gld_devlock);
714 
715 #ifdef DEBUG
716 	if (macinfo->gldm_ppa != ddi_get_instance(devinfo))
717 		cmn_err(CE_WARN, "%s%d instance != ppa %d",
718 		    ddi_driver_name(devinfo), ddi_get_instance(devinfo),
719 		    macinfo->gldm_ppa);
720 #endif
721 
722 	/*
723 	 * Create style 2 node (gated by gld-provider-styles property).
724 	 *
725 	 * NOTE: When the CLONE_DEV flag is specified to
726 	 *	 ddi_create_minor_node() the minor number argument is
727 	 *	 immaterial. Opens of that node will go via the clone
728 	 *	 driver and gld_open() will always be passed a dev_t with
729 	 *	 minor of zero.
730 	 */
731 	if (glddev->gld_styles != -2) {
732 		if (ddi_create_minor_node(devinfo, glddev->gld_name, S_IFCHR,
733 		    0, DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) {
734 			mutex_exit(&glddev->gld_devlock);
735 			goto late_failure;
736 		}
737 	}
738 
739 	/*
740 	 * Create style 1 node (gated by gld-provider-styles property)
741 	 */
742 	if (glddev->gld_styles != -1) {
743 		(void) sprintf(minordev, "%s%d", glddev->gld_name,
744 		    macinfo->gldm_ppa);
745 		if (ddi_create_minor_node(devinfo, minordev, S_IFCHR,
746 		    GLD_STYLE1_PPA_TO_MINOR(macinfo->gldm_ppa), DDI_NT_NET,
747 		    0) != DDI_SUCCESS) {
748 			mutex_exit(&glddev->gld_devlock);
749 			goto late_failure;
750 		}
751 	}
752 
753 	/* add ourselves to this major device's linked list of instances */
754 	gldinsque(macinfo, glddev->gld_mac_prev);
755 
756 	mutex_exit(&glddev->gld_devlock);
757 
758 	/*
759 	 * Unfortunately we need the ppa before we call gld_initstats();
760 	 * otherwise we would like to do this just above the mutex_enter
761 	 * above.  In which case we could have set MAC_READY inside the
762 	 * mutex and we wouldn't have needed to check it in open and
763 	 * DL_ATTACH.  We wouldn't like to do the initstats/kstat_create
764 	 * inside the mutex because it might get taken in our kstat_update
765 	 * routine and cause a deadlock with kstat_chain_lock.
766 	 */
767 
768 	/* gld_initstats() calls (*ifp->init)() */
769 	if (gld_initstats(macinfo) != GLD_SUCCESS) {
770 		mutex_enter(&glddev->gld_devlock);
771 		gldremque(macinfo);
772 		mutex_exit(&glddev->gld_devlock);
773 		goto late_failure;
774 	}
775 
776 	/*
777 	 * Need to indicate we are NOW ready to process interrupts;
778 	 * any interrupt before this is set is for someone else.
779 	 * This flag is also now used to tell open, et. al. that this
780 	 * mac is now fully ready and available for use.
781 	 */
782 	GLDM_LOCK(macinfo, RW_WRITER);
783 	macinfo->gldm_GLD_flags |= GLD_MAC_READY;
784 	GLDM_UNLOCK(macinfo);
785 
786 	/* log local ethernet address -- XXX not DDI compliant */
787 	if (macinfo->gldm_addrlen == sizeof (struct ether_addr))
788 		(void) localetheraddr(
789 		    (struct ether_addr *)macinfo->gldm_vendor_addr, NULL);
790 
791 	/* now put announcement into the message buffer */
792 	cmn_err(CE_CONT, "!%s%d: %s: type \"%s\" mac address %s\n",
793 	    glddev->gld_name,
794 	    macinfo->gldm_ppa, macinfo->gldm_ident,
795 	    mac_pvt->interfacep->mac_string,
796 	    gld_macaddr_sprintf(pbuf, macinfo->gldm_vendor_addr,
797 	    macinfo->gldm_addrlen));
798 
799 	ddi_report_dev(devinfo);
800 	return (DDI_SUCCESS);
801 
802 late_failure:
803 	ddi_remove_minor_node(devinfo, NULL);
804 	GLDM_LOCK_DESTROY(macinfo);
805 	if (mac_pvt->curr_macaddr != NULL)
806 	    kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
807 	if (mac_pvt->statistics != NULL)
808 	    kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
809 	kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
810 	macinfo->gldm_mac_pvt = NULL;
811 
812 failure:
813 	mutex_enter(&gld_device_list.gld_devlock);
814 	glddev->gld_ndevice--;
815 	/*
816 	 * Note that just because this goes to zero here does not necessarily
817 	 * mean that we were the one who added the glddev above.  It's
818 	 * possible that the first mac unattached while were were in here
819 	 * failing to attach the second mac.  But we're now the last.
820 	 */
821 	if (glddev->gld_ndevice == 0) {
822 		/* There should be no macinfos left */
823 		ASSERT(glddev->gld_mac_next ==
824 		    (gld_mac_info_t *)&glddev->gld_mac_next);
825 		ASSERT(glddev->gld_mac_prev ==
826 		    (gld_mac_info_t *)&glddev->gld_mac_next);
827 
828 		/*
829 		 * There should be no DL_UNATTACHED streams: the system
830 		 * should not have detached the "first" devinfo which has
831 		 * all the open style 2 streams.
832 		 *
833 		 * XXX This is not clear.  See gld_getinfo and Bug 1165519
834 		 */
835 		ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
836 		ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
837 
838 		gldremque(glddev);
839 		mutex_destroy(&glddev->gld_devlock);
840 		if (glddev->gld_broadcast != NULL)
841 			kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
842 		kmem_free(glddev, sizeof (glddev_t));
843 	}
844 	mutex_exit(&gld_device_list.gld_devlock);
845 
846 	return (DDI_FAILURE);
847 }
848 
849 /*
850  * gld_unregister (macinfo)
851  * remove the macinfo structure from local structures
852  * this is cleanup for a driver to be unloaded
853  */
854 int
855 gld_unregister(gld_mac_info_t *macinfo)
856 {
857 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
858 	glddev_t *glddev = mac_pvt->major_dev;
859 	gld_interface_t *ifp;
860 	int multisize = sizeof (gld_mcast_t) * glddev->gld_multisize;
861 
862 	mutex_enter(&glddev->gld_devlock);
863 	GLDM_LOCK(macinfo, RW_WRITER);
864 
865 	if (mac_pvt->nvlan > 0) {
866 		GLDM_UNLOCK(macinfo);
867 		mutex_exit(&glddev->gld_devlock);
868 		return (DDI_FAILURE);
869 	}
870 
871 #ifdef	GLD_DEBUG
872 	{
873 		int i;
874 
875 		for (i = 0; i < VLAN_HASHSZ; i++) {
876 			if ((mac_pvt->vlan_hash[i] != NULL))
877 				cmn_err(CE_PANIC,
878 				    "%s, line %d: "
879 				    "mac_pvt->vlan_hash[%d] != NULL",
880 				    __FILE__, __LINE__, i);
881 		}
882 	}
883 #endif
884 
885 	/* Delete this mac */
886 	gldremque(macinfo);
887 
888 	/* Disallow further entries to gld_recv() and gld_sched() */
889 	macinfo->gldm_GLD_flags |= GLD_UNREGISTERED;
890 
891 	GLDM_UNLOCK(macinfo);
892 	mutex_exit(&glddev->gld_devlock);
893 
894 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
895 	(*ifp->uninit)(macinfo);
896 
897 	ASSERT(mac_pvt->kstatp);
898 	kstat_delete(mac_pvt->kstatp);
899 
900 	ASSERT(GLDM_LOCK_INITED(macinfo));
901 	kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
902 	kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
903 
904 	if (mac_pvt->mcast_table != NULL)
905 		kmem_free(mac_pvt->mcast_table, multisize);
906 	kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
907 	macinfo->gldm_mac_pvt = (caddr_t)NULL;
908 
909 	/* We now have one fewer instance for this major device */
910 	mutex_enter(&gld_device_list.gld_devlock);
911 	glddev->gld_ndevice--;
912 	if (glddev->gld_ndevice == 0) {
913 		/* There should be no macinfos left */
914 		ASSERT(glddev->gld_mac_next ==
915 		    (gld_mac_info_t *)&glddev->gld_mac_next);
916 		ASSERT(glddev->gld_mac_prev ==
917 		    (gld_mac_info_t *)&glddev->gld_mac_next);
918 
919 		/*
920 		 * There should be no DL_UNATTACHED streams: the system
921 		 * should not have detached the "first" devinfo which has
922 		 * all the open style 2 streams.
923 		 *
924 		 * XXX This is not clear.  See gld_getinfo and Bug 1165519
925 		 */
926 		ASSERT(glddev->gld_str_next == (gld_t *)&glddev->gld_str_next);
927 		ASSERT(glddev->gld_str_prev == (gld_t *)&glddev->gld_str_next);
928 
929 		ddi_remove_minor_node(macinfo->gldm_devinfo, NULL);
930 		gldremque(glddev);
931 		mutex_destroy(&glddev->gld_devlock);
932 		if (glddev->gld_broadcast != NULL)
933 			kmem_free(glddev->gld_broadcast, glddev->gld_addrlen);
934 		kmem_free(glddev, sizeof (glddev_t));
935 	}
936 	mutex_exit(&gld_device_list.gld_devlock);
937 
938 	return (DDI_SUCCESS);
939 }
940 
941 /*
942  * gld_initstats
943  * called from gld_register
944  */
945 static int
946 gld_initstats(gld_mac_info_t *macinfo)
947 {
948 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
949 	struct gldkstats *sp;
950 	glddev_t *glddev;
951 	kstat_t *ksp;
952 	gld_interface_t *ifp;
953 
954 	glddev = mac_pvt->major_dev;
955 
956 	if ((ksp = kstat_create(glddev->gld_name, macinfo->gldm_ppa,
957 	    NULL, "net", KSTAT_TYPE_NAMED,
958 	    sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) {
959 		cmn_err(CE_WARN,
960 		    "GLD: failed to create kstat structure for %s%d",
961 		    glddev->gld_name, macinfo->gldm_ppa);
962 		return (GLD_FAILURE);
963 	}
964 	mac_pvt->kstatp = ksp;
965 
966 	ksp->ks_update = gld_update_kstat;
967 	ksp->ks_private = (void *)macinfo;
968 
969 	sp = ksp->ks_data;
970 	kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32);
971 	kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32);
972 	kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG);
973 	kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG);
974 	kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32);
975 	kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32);
976 	kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG);
977 	kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG);
978 	kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG);
979 	kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG);
980 	kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG);
981 	kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG);
982 	kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG);
983 	kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG);
984 	kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG);
985 	kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64);
986 	kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64);
987 	kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64);
988 	kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64);
989 	kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG);
990 	kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64);
991 	kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR);
992 	kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR);
993 
994 	kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG);
995 	kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG);
996 	kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG);
997 
998 	kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp",
999 	    KSTAT_DATA_UINT32);
1000 	kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp",
1001 	    KSTAT_DATA_UINT32);
1002 
1003 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
1004 
1005 	(*ifp->init)(macinfo);
1006 
1007 	kstat_install(ksp);
1008 
1009 	return (GLD_SUCCESS);
1010 }
1011 
1012 /* called from kstat mechanism, and from wsrv's get_statistics_req */
1013 static int
1014 gld_update_kstat(kstat_t *ksp, int rw)
1015 {
1016 	gld_mac_info_t	*macinfo;
1017 	gld_mac_pvt_t	*mac_pvt;
1018 	struct gldkstats *gsp;
1019 	struct gld_stats *stats;
1020 
1021 	if (rw == KSTAT_WRITE)
1022 		return (EACCES);
1023 
1024 	macinfo = (gld_mac_info_t *)ksp->ks_private;
1025 	ASSERT(macinfo != NULL);
1026 
1027 	GLDM_LOCK(macinfo, RW_WRITER);
1028 
1029 	if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) {
1030 		GLDM_UNLOCK(macinfo);
1031 		return (EIO);	/* this one's not ready yet */
1032 	}
1033 
1034 	if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
1035 		GLDM_UNLOCK(macinfo);
1036 		return (EIO);	/* this one's not ready any more */
1037 	}
1038 
1039 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1040 	gsp = mac_pvt->kstatp->ks_data;
1041 	ASSERT(gsp);
1042 	stats = mac_pvt->statistics;
1043 
1044 	if (macinfo->gldm_get_stats)
1045 		(void) (*macinfo->gldm_get_stats)(macinfo, stats);
1046 
1047 	gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff;
1048 	gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff;
1049 	gsp->glds_multixmt.value.ul = stats->glds_multixmt;
1050 	gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt;
1051 	gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf;	/* 0 for now */
1052 	gsp->glds_xmtretry.value.ul = stats->glds_xmtretry;
1053 
1054 	gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64;
1055 	gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64;
1056 	gsp->glds_xmtbadinterp.value.ui32 = stats->glds_xmtbadinterp;
1057 
1058 	gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff;
1059 	gsp->glds_errxmt.value.ul = stats->glds_errxmt;
1060 	gsp->glds_errrcv.value.ul = stats->glds_errrcv;
1061 	gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff;
1062 	gsp->glds_multircv.value.ul = stats->glds_multircv;
1063 	gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv;
1064 	gsp->glds_blocked.value.ul = stats->glds_blocked;
1065 	gsp->glds_overflow.value.ul = stats->glds_overflow;
1066 	gsp->glds_underflow.value.ul = stats->glds_underflow;
1067 	gsp->glds_missed.value.ul = stats->glds_missed;
1068 	gsp->glds_norcvbuf.value.ul = stats->glds_norcvbuf +
1069 	    stats->glds_gldnorcvbuf;
1070 	gsp->glds_intr.value.ul = stats->glds_intr;
1071 
1072 	gsp->glds_speed.value.ui64 = stats->glds_speed;
1073 	gsp->glds_unknowns.value.ul = stats->glds_unknowns;
1074 	gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64;
1075 	gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64;
1076 	gsp->glds_rcvbadinterp.value.ui32 = stats->glds_rcvbadinterp;
1077 
1078 	if (mac_pvt->nprom)
1079 		(void) strcpy(gsp->glds_prom.value.c, "phys");
1080 	else if (mac_pvt->nprom_multi)
1081 		(void) strcpy(gsp->glds_prom.value.c, "multi");
1082 	else
1083 		(void) strcpy(gsp->glds_prom.value.c, "off");
1084 
1085 	(void) strcpy(gsp->glds_media.value.c, gld_media[
1086 	    stats->glds_media < sizeof (gld_media) / sizeof (gld_media[0])
1087 	    ? stats->glds_media : 0]);
1088 
1089 	switch (macinfo->gldm_type) {
1090 	case DL_ETHER:
1091 		gsp->glds_frame.value.ul = stats->glds_frame;
1092 		gsp->glds_crc.value.ul = stats->glds_crc;
1093 		gsp->glds_collisions.value.ul = stats->glds_collisions;
1094 		gsp->glds_excoll.value.ul = stats->glds_excoll;
1095 		gsp->glds_defer.value.ul = stats->glds_defer;
1096 		gsp->glds_short.value.ul = stats->glds_short;
1097 		gsp->glds_xmtlatecoll.value.ul = stats->glds_xmtlatecoll;
1098 		gsp->glds_nocarrier.value.ul = stats->glds_nocarrier;
1099 		gsp->glds_dot3_first_coll.value.ui32 =
1100 		    stats->glds_dot3_first_coll;
1101 		gsp->glds_dot3_multi_coll.value.ui32 =
1102 		    stats->glds_dot3_multi_coll;
1103 		gsp->glds_dot3_sqe_error.value.ui32 =
1104 		    stats->glds_dot3_sqe_error;
1105 		gsp->glds_dot3_mac_xmt_error.value.ui32 =
1106 		    stats->glds_dot3_mac_xmt_error;
1107 		gsp->glds_dot3_mac_rcv_error.value.ui32 =
1108 		    stats->glds_dot3_mac_rcv_error;
1109 		gsp->glds_dot3_frame_too_long.value.ui32 =
1110 		    stats->glds_dot3_frame_too_long;
1111 		(void) strcpy(gsp->glds_duplex.value.c, gld_duplex[
1112 		    stats->glds_duplex <
1113 		    sizeof (gld_duplex) / sizeof (gld_duplex[0]) ?
1114 		    stats->glds_duplex : 0]);
1115 		break;
1116 	case DL_TPR:
1117 		gsp->glds_dot5_line_error.value.ui32 =
1118 		    stats->glds_dot5_line_error;
1119 		gsp->glds_dot5_burst_error.value.ui32 =
1120 		    stats->glds_dot5_burst_error;
1121 		gsp->glds_dot5_signal_loss.value.ui32 =
1122 		    stats->glds_dot5_signal_loss;
1123 		gsp->glds_dot5_ace_error.value.ui32 =
1124 		    stats->glds_dot5_ace_error;
1125 		gsp->glds_dot5_internal_error.value.ui32 =
1126 		    stats->glds_dot5_internal_error;
1127 		gsp->glds_dot5_lost_frame_error.value.ui32 =
1128 		    stats->glds_dot5_lost_frame_error;
1129 		gsp->glds_dot5_frame_copied_error.value.ui32 =
1130 		    stats->glds_dot5_frame_copied_error;
1131 		gsp->glds_dot5_token_error.value.ui32 =
1132 		    stats->glds_dot5_token_error;
1133 		gsp->glds_dot5_freq_error.value.ui32 =
1134 		    stats->glds_dot5_freq_error;
1135 		break;
1136 	case DL_FDDI:
1137 		gsp->glds_fddi_mac_error.value.ui32 =
1138 		    stats->glds_fddi_mac_error;
1139 		gsp->glds_fddi_mac_lost.value.ui32 =
1140 		    stats->glds_fddi_mac_lost;
1141 		gsp->glds_fddi_mac_token.value.ui32 =
1142 		    stats->glds_fddi_mac_token;
1143 		gsp->glds_fddi_mac_tvx_expired.value.ui32 =
1144 		    stats->glds_fddi_mac_tvx_expired;
1145 		gsp->glds_fddi_mac_late.value.ui32 =
1146 		    stats->glds_fddi_mac_late;
1147 		gsp->glds_fddi_mac_ring_op.value.ui32 =
1148 		    stats->glds_fddi_mac_ring_op;
1149 		break;
1150 	case DL_IB:
1151 		break;
1152 	default:
1153 		break;
1154 	}
1155 
1156 	GLDM_UNLOCK(macinfo);
1157 
1158 #ifdef GLD_DEBUG
1159 	gld_check_assertions();
1160 	if (gld_debug & GLDRDE)
1161 		gld_sr_dump(macinfo);
1162 #endif
1163 
1164 	return (0);
1165 }
1166 
1167 static int
1168 gld_init_vlan_stats(gld_vlan_t *vlan)
1169 {
1170 	gld_mac_info_t *mac = vlan->gldv_mac;
1171 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
1172 	struct gldkstats *sp;
1173 	glddev_t *glddev;
1174 	kstat_t *ksp;
1175 	char *name;
1176 	int instance;
1177 
1178 	glddev = mac_pvt->major_dev;
1179 	name = glddev->gld_name;
1180 	instance = (vlan->gldv_id * GLD_VLAN_SCALE) + mac->gldm_ppa;
1181 
1182 	if ((ksp = kstat_create(name, instance,
1183 	    NULL, "net", KSTAT_TYPE_NAMED,
1184 	    sizeof (struct gldkstats) / sizeof (kstat_named_t), 0)) == NULL) {
1185 		cmn_err(CE_WARN,
1186 		    "GLD: failed to create kstat structure for %s%d",
1187 		    name, instance);
1188 		return (GLD_FAILURE);
1189 	}
1190 
1191 	vlan->gldv_kstatp = ksp;
1192 
1193 	ksp->ks_update = gld_update_vlan_kstat;
1194 	ksp->ks_private = (void *)vlan;
1195 
1196 	sp = ksp->ks_data;
1197 	kstat_named_init(&sp->glds_pktrcv, "ipackets", KSTAT_DATA_UINT32);
1198 	kstat_named_init(&sp->glds_pktxmt, "opackets", KSTAT_DATA_UINT32);
1199 	kstat_named_init(&sp->glds_errrcv, "ierrors", KSTAT_DATA_ULONG);
1200 	kstat_named_init(&sp->glds_errxmt, "oerrors", KSTAT_DATA_ULONG);
1201 	kstat_named_init(&sp->glds_bytexmt, "obytes", KSTAT_DATA_UINT32);
1202 	kstat_named_init(&sp->glds_bytercv, "rbytes", KSTAT_DATA_UINT32);
1203 	kstat_named_init(&sp->glds_multixmt, "multixmt", KSTAT_DATA_ULONG);
1204 	kstat_named_init(&sp->glds_multircv, "multircv", KSTAT_DATA_ULONG);
1205 	kstat_named_init(&sp->glds_brdcstxmt, "brdcstxmt", KSTAT_DATA_ULONG);
1206 	kstat_named_init(&sp->glds_brdcstrcv, "brdcstrcv", KSTAT_DATA_ULONG);
1207 	kstat_named_init(&sp->glds_blocked, "blocked", KSTAT_DATA_ULONG);
1208 	kstat_named_init(&sp->glds_noxmtbuf, "noxmtbuf", KSTAT_DATA_ULONG);
1209 	kstat_named_init(&sp->glds_norcvbuf, "norcvbuf", KSTAT_DATA_ULONG);
1210 	kstat_named_init(&sp->glds_xmtretry, "xmtretry", KSTAT_DATA_ULONG);
1211 	kstat_named_init(&sp->glds_intr, "intr", KSTAT_DATA_ULONG);
1212 	kstat_named_init(&sp->glds_pktrcv64, "ipackets64", KSTAT_DATA_UINT64);
1213 	kstat_named_init(&sp->glds_pktxmt64, "opackets64", KSTAT_DATA_UINT64);
1214 	kstat_named_init(&sp->glds_bytexmt64, "obytes64", KSTAT_DATA_UINT64);
1215 	kstat_named_init(&sp->glds_bytercv64, "rbytes64", KSTAT_DATA_UINT64);
1216 	kstat_named_init(&sp->glds_unknowns, "unknowns", KSTAT_DATA_ULONG);
1217 	kstat_named_init(&sp->glds_speed, "ifspeed", KSTAT_DATA_UINT64);
1218 	kstat_named_init(&sp->glds_media, "media", KSTAT_DATA_CHAR);
1219 	kstat_named_init(&sp->glds_prom, "promisc", KSTAT_DATA_CHAR);
1220 
1221 	kstat_named_init(&sp->glds_overflow, "oflo", KSTAT_DATA_ULONG);
1222 	kstat_named_init(&sp->glds_underflow, "uflo", KSTAT_DATA_ULONG);
1223 	kstat_named_init(&sp->glds_missed, "missed", KSTAT_DATA_ULONG);
1224 
1225 	kstat_named_init(&sp->glds_xmtbadinterp, "xmt_badinterp",
1226 	    KSTAT_DATA_UINT32);
1227 	kstat_named_init(&sp->glds_rcvbadinterp, "rcv_badinterp",
1228 	    KSTAT_DATA_UINT32);
1229 
1230 	kstat_install(ksp);
1231 	return (GLD_SUCCESS);
1232 }
1233 
1234 static int
1235 gld_update_vlan_kstat(kstat_t *ksp, int rw)
1236 {
1237 	gld_vlan_t	*vlan;
1238 	gld_mac_info_t	*macinfo;
1239 	struct gldkstats *gsp;
1240 	struct gld_stats *stats;
1241 
1242 	if (rw == KSTAT_WRITE)
1243 		return (EACCES);
1244 
1245 	vlan = (gld_vlan_t *)ksp->ks_private;
1246 	ASSERT(vlan != NULL);
1247 
1248 	macinfo = vlan->gldv_mac;
1249 	GLDM_LOCK(macinfo, RW_WRITER);
1250 
1251 	gsp = vlan->gldv_kstatp->ks_data;
1252 	ASSERT(gsp);
1253 	stats = vlan->gldv_stats;
1254 
1255 	gsp->glds_pktxmt.value.ui32 = stats->glds_pktxmt64 & 0xffffffff;
1256 	gsp->glds_bytexmt.value.ui32 = stats->glds_bytexmt64 & 0xffffffff;
1257 	gsp->glds_errxmt.value.ul = stats->glds_errxmt;
1258 	gsp->glds_multixmt.value.ul = stats->glds_multixmt;
1259 	gsp->glds_brdcstxmt.value.ul = stats->glds_brdcstxmt;
1260 	gsp->glds_noxmtbuf.value.ul = stats->glds_noxmtbuf;
1261 	gsp->glds_xmtretry.value.ul = stats->glds_xmtretry;
1262 	gsp->glds_pktxmt64.value.ui64 = stats->glds_pktxmt64;
1263 	gsp->glds_bytexmt64.value.ui64 = stats->glds_bytexmt64;
1264 
1265 	gsp->glds_pktrcv.value.ui32 = stats->glds_pktrcv64 & 0xffffffff;
1266 	gsp->glds_bytercv.value.ui32 = stats->glds_bytercv64 & 0xffffffff;
1267 	gsp->glds_errrcv.value.ul = stats->glds_errrcv;
1268 	gsp->glds_multircv.value.ul = stats->glds_multircv;
1269 	gsp->glds_brdcstrcv.value.ul = stats->glds_brdcstrcv;
1270 	gsp->glds_blocked.value.ul = stats->glds_blocked;
1271 	gsp->glds_pktrcv64.value.ui64 = stats->glds_pktrcv64;
1272 	gsp->glds_bytercv64.value.ui64 = stats->glds_bytercv64;
1273 
1274 	GLDM_UNLOCK(macinfo);
1275 	return (0);
1276 }
1277 
1278 /*
1279  * The device dependent driver specifies gld_getinfo as its getinfo routine.
1280  */
1281 /*ARGSUSED*/
1282 int
1283 gld_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1284 {
1285 	dev_info_t	*devinfo;
1286 	minor_t		minor = getminor((dev_t)arg);
1287 	int		rc = DDI_FAILURE;
1288 
1289 	switch (cmd) {
1290 	case DDI_INFO_DEVT2DEVINFO:
1291 		if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) {
1292 			*(dev_info_t **)resultp = devinfo;
1293 			rc = DDI_SUCCESS;
1294 		}
1295 		break;
1296 	case DDI_INFO_DEVT2INSTANCE:
1297 		/* Need static mapping for deferred attach */
1298 		if (minor == GLD_USE_STYLE2) {
1299 			/*
1300 			 * Style 2:  this minor number does not correspond to
1301 			 * any particular instance number.
1302 			 */
1303 			rc = DDI_FAILURE;
1304 		} else if (minor <= GLD_MAX_STYLE1_MINOR) {
1305 			/* Style 1:  calculate the PPA from the minor */
1306 			*resultp = (void *)GLD_STYLE1_MINOR_TO_PPA(minor);
1307 			rc = DDI_SUCCESS;
1308 		} else {
1309 			/* Clone:  look for it.  Not a static mapping */
1310 			if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) {
1311 				*resultp = (void *)ddi_get_instance(devinfo);
1312 				rc = DDI_SUCCESS;
1313 			}
1314 		}
1315 		break;
1316 	}
1317 
1318 	return (rc);
1319 }
1320 
1321 /* called from gld_getinfo */
1322 dev_info_t *
1323 gld_finddevinfo(dev_t dev)
1324 {
1325 	minor_t		minor = getminor(dev);
1326 	glddev_t	*device;
1327 	gld_mac_info_t	*mac;
1328 	gld_vlan_t	*vlan;
1329 	gld_t		*str;
1330 	dev_info_t	*devinfo = NULL;
1331 	int		i;
1332 
1333 	if (minor == GLD_USE_STYLE2) {
1334 		/*
1335 		 * Style 2:  this minor number does not correspond to
1336 		 * any particular instance number.
1337 		 *
1338 		 * XXX We don't know what to say.  See Bug 1165519.
1339 		 */
1340 		return (NULL);
1341 	}
1342 
1343 	mutex_enter(&gld_device_list.gld_devlock);	/* hold the device */
1344 
1345 	device = gld_devlookup(getmajor(dev));
1346 	if (device == NULL) {
1347 		/* There are no attached instances of this device */
1348 		mutex_exit(&gld_device_list.gld_devlock);
1349 		return (NULL);
1350 	}
1351 
1352 	/*
1353 	 * Search all attached macs and streams.
1354 	 *
1355 	 * XXX We don't bother checking the DL_UNATTACHED streams since
1356 	 * we don't know what devinfo we should report back even if we
1357 	 * found the minor.  Maybe we should associate streams that are
1358 	 * not currently attached to a PPA with the "first" devinfo node
1359 	 * of the major device to attach -- the one that created the
1360 	 * minor node for the generic device.
1361 	 */
1362 	mutex_enter(&device->gld_devlock);
1363 
1364 	for (mac = device->gld_mac_next;
1365 	    mac != (gld_mac_info_t *)&device->gld_mac_next;
1366 	    mac = mac->gldm_next) {
1367 		gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
1368 
1369 		if (!(mac->gldm_GLD_flags & GLD_MAC_READY))
1370 			continue;	/* this one's not ready yet */
1371 		if (minor <= GLD_MAX_STYLE1_MINOR) {
1372 			/* Style 1 -- look for the corresponding PPA */
1373 			if (minor == GLD_STYLE1_PPA_TO_MINOR(mac->gldm_ppa)) {
1374 				devinfo = mac->gldm_devinfo;
1375 				goto out;	/* found it! */
1376 			} else
1377 				continue;	/* not this PPA */
1378 		}
1379 
1380 		/* We are looking for a clone */
1381 		for (i = 0; i < VLAN_HASHSZ; i++) {
1382 			for (vlan = pvt->vlan_hash[i];
1383 			    vlan != NULL; vlan = vlan->gldv_next) {
1384 				for (str = vlan->gldv_str_next;
1385 				    str != (gld_t *)&vlan->gldv_str_next;
1386 				    str = str->gld_next) {
1387 					ASSERT(str->gld_mac_info == mac);
1388 					if (minor == str->gld_minor) {
1389 						devinfo = mac->gldm_devinfo;
1390 						goto out;
1391 					}
1392 				}
1393 			}
1394 		}
1395 	}
1396 out:
1397 	mutex_exit(&device->gld_devlock);
1398 	mutex_exit(&gld_device_list.gld_devlock);
1399 	return (devinfo);
1400 }
1401 
1402 /*
1403  * STREAMS open routine.  The device dependent driver specifies this as its
1404  * open entry point.
1405  */
1406 /*ARGSUSED2*/
1407 int
1408 gld_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
1409 {
1410 	gld_mac_pvt_t *mac_pvt;
1411 	gld_t *gld;
1412 	glddev_t *glddev;
1413 	gld_mac_info_t *macinfo;
1414 	minor_t minor = getminor(*dev);
1415 	gld_vlan_t *vlan;
1416 	t_uscalar_t ppa;
1417 
1418 	ASSERT(q != NULL);
1419 
1420 	if (minor > GLD_MAX_STYLE1_MINOR)
1421 		return (ENXIO);
1422 
1423 	ASSERT(q->q_ptr == NULL);	/* Clone device gives us a fresh Q */
1424 
1425 	/* Find our per-major glddev_t structure */
1426 	mutex_enter(&gld_device_list.gld_devlock);
1427 	glddev = gld_devlookup(getmajor(*dev));
1428 
1429 	/*
1430 	 * This glddev will hang around since detach (and therefore
1431 	 * gld_unregister) can't run while we're here in the open routine.
1432 	 */
1433 	mutex_exit(&gld_device_list.gld_devlock);
1434 
1435 	if (glddev == NULL)
1436 		return (ENXIO);
1437 
1438 #ifdef GLD_DEBUG
1439 	if (gld_debug & GLDPROT) {
1440 		if (minor == GLD_USE_STYLE2)
1441 			cmn_err(CE_NOTE, "gld_open(%p, Style 2)", (void *)q);
1442 		else
1443 			cmn_err(CE_NOTE, "gld_open(%p, Style 1, minor = %d)",
1444 			    (void *)q, minor);
1445 	}
1446 #endif
1447 
1448 	/*
1449 	 * get a per-stream structure and link things together so we
1450 	 * can easily find them later.
1451 	 */
1452 	gld = kmem_zalloc(sizeof (gld_t), KM_SLEEP);
1453 
1454 	/*
1455 	 * fill in the structure and state info
1456 	 */
1457 	gld->gld_qptr = q;
1458 	gld->gld_device = glddev;
1459 	gld->gld_state = DL_UNATTACHED;
1460 
1461 	/*
1462 	 * we must atomically find a free minor number and add the stream
1463 	 * to a list, because gld_findminor has to traverse the lists to
1464 	 * determine which minor numbers are free.
1465 	 */
1466 	mutex_enter(&glddev->gld_devlock);
1467 
1468 	/* find a free minor device number for the clone */
1469 	gld->gld_minor = gld_findminor(glddev);
1470 	if (gld->gld_minor == 0) {
1471 		mutex_exit(&glddev->gld_devlock);
1472 		kmem_free(gld, sizeof (gld_t));
1473 		return (ENOSR);
1474 	}
1475 
1476 #ifdef GLD_VERBOSE_DEBUG
1477 	if (gld_debug & GLDPROT)
1478 		cmn_err(CE_NOTE, "gld_open() gld ptr: %p minor: %d",
1479 		    (void *)gld, gld->gld_minor);
1480 #endif
1481 
1482 	if (minor == GLD_USE_STYLE2) {
1483 		gld->gld_style = DL_STYLE2;
1484 		*dev = makedevice(getmajor(*dev), gld->gld_minor);
1485 		WR(q)->q_ptr = q->q_ptr = (caddr_t)gld;
1486 		gldinsque(gld, glddev->gld_str_prev);
1487 #ifdef GLD_VERBOSE_DEBUG
1488 		if (gld_debug & GLDPROT)
1489 			cmn_err(CE_NOTE, "GLDstruct added to device list");
1490 #endif
1491 		(void) qassociate(q, -1);
1492 		goto done;
1493 	}
1494 
1495 	gld->gld_style = DL_STYLE1;
1496 
1497 	/* the PPA is actually 1 less than the minordev */
1498 	ppa = GLD_STYLE1_MINOR_TO_PPA(minor);
1499 
1500 	for (macinfo = glddev->gld_mac_next;
1501 	    macinfo != (gld_mac_info_t *)(&glddev->gld_mac_next);
1502 	    macinfo = macinfo->gldm_next) {
1503 		ASSERT(macinfo != NULL);
1504 		if (macinfo->gldm_ppa != ppa)
1505 			continue;
1506 
1507 		if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
1508 			continue;	/* this one's not ready yet */
1509 
1510 		/*
1511 		 * we found the correct PPA
1512 		 */
1513 		GLDM_LOCK(macinfo, RW_WRITER);
1514 
1515 		gld->gld_mac_info = macinfo;
1516 
1517 		if (macinfo->gldm_send_tagged != NULL)
1518 			gld->gld_send = macinfo->gldm_send_tagged;
1519 		else
1520 			gld->gld_send = macinfo->gldm_send;
1521 
1522 		/* now ready for action */
1523 		gld->gld_state = DL_UNBOUND;
1524 
1525 		if ((vlan = gld_get_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
1526 			GLDM_UNLOCK(macinfo);
1527 			mutex_exit(&glddev->gld_devlock);
1528 			kmem_free(gld, sizeof (gld_t));
1529 			return (EIO);
1530 		}
1531 
1532 		mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1533 		if (!mac_pvt->started) {
1534 			if (gld_start_mac(macinfo) != GLD_SUCCESS) {
1535 				gld_rem_vlan(vlan);
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