xref: /titanic_44/usr/src/uts/common/io/gld.c (revision 5c46c6a053defc1bf25f2e08df2653bc7717ed0b)
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 *)(uintptr_t)
1307 			    GLD_STYLE1_MINOR_TO_PPA(minor);
1308 			rc = DDI_SUCCESS;
1309 		} else {
1310 			/* Clone:  look for it.  Not a static mapping */
1311 			if ((devinfo = gld_finddevinfo((dev_t)arg)) != NULL) {
1312 				*resultp = (void *)(uintptr_t)
1313 				    ddi_get_instance(devinfo);
1314 				rc = DDI_SUCCESS;
1315 			}
1316 		}
1317 		break;
1318 	}
1319 
1320 	return (rc);
1321 }
1322 
1323 /* called from gld_getinfo */
1324 dev_info_t *
1325 gld_finddevinfo(dev_t dev)
1326 {
1327 	minor_t		minor = getminor(dev);
1328 	glddev_t	*device;
1329 	gld_mac_info_t	*mac;
1330 	gld_vlan_t	*vlan;
1331 	gld_t		*str;
1332 	dev_info_t	*devinfo = NULL;
1333 	int		i;
1334 
1335 	if (minor == GLD_USE_STYLE2) {
1336 		/*
1337 		 * Style 2:  this minor number does not correspond to
1338 		 * any particular instance number.
1339 		 *
1340 		 * XXX We don't know what to say.  See Bug 1165519.
1341 		 */
1342 		return (NULL);
1343 	}
1344 
1345 	mutex_enter(&gld_device_list.gld_devlock);	/* hold the device */
1346 
1347 	device = gld_devlookup(getmajor(dev));
1348 	if (device == NULL) {
1349 		/* There are no attached instances of this device */
1350 		mutex_exit(&gld_device_list.gld_devlock);
1351 		return (NULL);
1352 	}
1353 
1354 	/*
1355 	 * Search all attached macs and streams.
1356 	 *
1357 	 * XXX We don't bother checking the DL_UNATTACHED streams since
1358 	 * we don't know what devinfo we should report back even if we
1359 	 * found the minor.  Maybe we should associate streams that are
1360 	 * not currently attached to a PPA with the "first" devinfo node
1361 	 * of the major device to attach -- the one that created the
1362 	 * minor node for the generic device.
1363 	 */
1364 	mutex_enter(&device->gld_devlock);
1365 
1366 	for (mac = device->gld_mac_next;
1367 	    mac != (gld_mac_info_t *)&device->gld_mac_next;
1368 	    mac = mac->gldm_next) {
1369 		gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
1370 
1371 		if (!(mac->gldm_GLD_flags & GLD_MAC_READY))
1372 			continue;	/* this one's not ready yet */
1373 		if (minor <= GLD_MAX_STYLE1_MINOR) {
1374 			/* Style 1 -- look for the corresponding PPA */
1375 			if (minor == GLD_STYLE1_PPA_TO_MINOR(mac->gldm_ppa)) {
1376 				devinfo = mac->gldm_devinfo;
1377 				goto out;	/* found it! */
1378 			} else
1379 				continue;	/* not this PPA */
1380 		}
1381 
1382 		/* We are looking for a clone */
1383 		for (i = 0; i < VLAN_HASHSZ; i++) {
1384 			for (vlan = pvt->vlan_hash[i];
1385 			    vlan != NULL; vlan = vlan->gldv_next) {
1386 				for (str = vlan->gldv_str_next;
1387 				    str != (gld_t *)&vlan->gldv_str_next;
1388 				    str = str->gld_next) {
1389 					ASSERT(str->gld_mac_info == mac);
1390 					if (minor == str->gld_minor) {
1391 						devinfo = mac->gldm_devinfo;
1392 						goto out;
1393 					}
1394 				}
1395 			}
1396 		}
1397 	}
1398 out:
1399 	mutex_exit(&device->gld_devlock);
1400 	mutex_exit(&gld_device_list.gld_devlock);
1401 	return (devinfo);
1402 }
1403 
1404 /*
1405  * STREAMS open routine.  The device dependent driver specifies this as its
1406  * open entry point.
1407  */
1408 /*ARGSUSED2*/
1409 int
1410 gld_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
1411 {
1412 	gld_mac_pvt_t *mac_pvt;
1413 	gld_t *gld;
1414 	glddev_t *glddev;
1415 	gld_mac_info_t *macinfo;
1416 	minor_t minor = getminor(*dev);
1417 	gld_vlan_t *vlan;
1418 	t_uscalar_t ppa;
1419 
1420 	ASSERT(q != NULL);
1421 
1422 	if (minor > GLD_MAX_STYLE1_MINOR)
1423 		return (ENXIO);
1424 
1425 	ASSERT(q->q_ptr == NULL);	/* Clone device gives us a fresh Q */
1426 
1427 	/* Find our per-major glddev_t structure */
1428 	mutex_enter(&gld_device_list.gld_devlock);
1429 	glddev = gld_devlookup(getmajor(*dev));
1430 
1431 	/*
1432 	 * This glddev will hang around since detach (and therefore
1433 	 * gld_unregister) can't run while we're here in the open routine.
1434 	 */
1435 	mutex_exit(&gld_device_list.gld_devlock);
1436 
1437 	if (glddev == NULL)
1438 		return (ENXIO);
1439 
1440 #ifdef GLD_DEBUG
1441 	if (gld_debug & GLDPROT) {
1442 		if (minor == GLD_USE_STYLE2)
1443 			cmn_err(CE_NOTE, "gld_open(%p, Style 2)", (void *)q);
1444 		else
1445 			cmn_err(CE_NOTE, "gld_open(%p, Style 1, minor = %d)",
1446 			    (void *)q, minor);
1447 	}
1448 #endif
1449 
1450 	/*
1451 	 * get a per-stream structure and link things together so we
1452 	 * can easily find them later.
1453 	 */
1454 	gld = kmem_zalloc(sizeof (gld_t), KM_SLEEP);
1455 
1456 	/*
1457 	 * fill in the structure and state info
1458 	 */
1459 	gld->gld_qptr = q;
1460 	gld->gld_device = glddev;
1461 	gld->gld_state = DL_UNATTACHED;
1462 
1463 	/*
1464 	 * we must atomically find a free minor number and add the stream
1465 	 * to a list, because gld_findminor has to traverse the lists to
1466 	 * determine which minor numbers are free.
1467 	 */
1468 	mutex_enter(&glddev->gld_devlock);
1469 
1470 	/* find a free minor device number for the clone */
1471 	gld->gld_minor = gld_findminor(glddev);
1472 	if (gld->gld_minor == 0) {
1473 		mutex_exit(&glddev->gld_devlock);
1474 		kmem_free(gld, sizeof (gld_t));
1475 		return (ENOSR);
1476 	}
1477 
1478 #ifdef GLD_VERBOSE_DEBUG
1479 	if (gld_debug & GLDPROT)
1480 		cmn_err(CE_NOTE, "gld_open() gld ptr: %p minor: %d",
1481 		    (void *)gld, gld->gld_minor);
1482 #endif
1483 
1484 	if (minor == GLD_USE_STYLE2) {
1485 		gld->gld_style = DL_STYLE2;
1486 		*dev = makedevice(getmajor(*dev), gld->gld_minor);
1487 		WR(q)->q_ptr = q->q_ptr = (caddr_t)gld;
1488 		gldinsque(gld, glddev->gld_str_prev);
1489 #ifdef GLD_VERBOSE_DEBUG
1490 		if (gld_debug & GLDPROT)
1491 			cmn_err(CE_NOTE, "GLDstruct added to device list");
1492 #endif
1493 		(void) qassociate(q, -1);
1494 		goto done;
1495 	}
1496 
1497 	gld->gld_style = DL_STYLE1;
1498 
1499 	/* the PPA is actually 1 less than the minordev */
1500 	ppa = GLD_STYLE1_MINOR_TO_PPA(minor);
1501 
1502 	for (macinfo = glddev->gld_mac_next;
1503 	    macinfo != (gld_mac_info_t *)(&glddev->gld_mac_next);
1504 	    macinfo = macinfo->gldm_next) {
1505 		ASSERT(macinfo != NULL);
1506 		if (macinfo->gldm_ppa != ppa)
1507 			continue;
1508 
1509 		if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
1510 			continue;	/* this one's not ready yet */
1511 
1512 		/*
1513 		 * we found the correct PPA
1514 		 */
1515 		GLDM_LOCK(macinfo, RW_WRITER);
1516 
1517 		gld->gld_mac_info = macinfo;
1518 
1519 		if (macinfo->gldm_send_tagged != NULL)
1520 			gld->gld_send = macinfo->gldm_send_tagged;
1521 		else
1522 			gld->gld_send = macinfo->gldm_send;
1523 
1524 		/* now ready for action */
1525 		gld->gld_state = DL_UNBOUND;
1526 
1527 		if ((vlan = gld_get_vlan(macinfo, VLAN_VID_NONE)) == NULL) {
1528 			GLDM_UNLOCK(macinfo);
1529 			mutex_exit(&glddev->gld_devlock);
1530 			kmem_free(gld, sizeof (gld_t));
1531 			return (EIO);
1532 		}
1533 
1534 		mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1535 		if (!mac_pvt->started) {
1536 			if (gld_start_mac(macinfo) != GLD_SUCCESS) {
1537 				gld_rem_vlan(vlan);
1538 				GLDM_UNLOCK(macinfo);
1539 				mutex_exit(&glddev->gld_devlock);
1540 				kmem_free(gld, sizeof (gld_t));
1541 				return (EIO);
1542 			}
1543 		}
1544 
1545 		gld->gld_vlan = vlan;
1546 		vlan->gldv_nstreams++;
1547 		gldinsque(gld, vlan->gldv_str_prev);
1548 		*dev = makedevice(getmajor(*dev), gld->gld_minor);
1549 		WR(q)->q_ptr = q->q_ptr = (caddr_t)gld;
1550 
1551 		GLDM_UNLOCK(macinfo);
1552 #ifdef GLD_VERBOSE_DEBUG
1553 		if (gld_debug & GLDPROT)
1554 			cmn_err(CE_NOTE,
1555 			    "GLDstruct added to instance list");
1556 #endif
1557 		break;
1558 	}
1559 
1560 	if (gld->gld_state == DL_UNATTACHED) {
1561 		mutex_exit(&glddev->gld_devlock);
1562 		kmem_free(gld, sizeof (gld_t));
1563 		return (ENXIO);
1564 	}
1565 
1566 done:
1567 	mutex_exit(&glddev->gld_devlock);
1568 	noenable(WR(q));	/* We'll do the qenables manually */
1569 	qprocson(q);		/* start the queues running */
1570 	qenable(WR(q));
1571 	return (0);
1572 }
1573 
1574 /*
1575  * normal stream close call checks current status and cleans up
1576  * data structures that were dynamically allocated
1577  */
1578 /*ARGSUSED1*/
1579 int
1580 gld_close(queue_t *q, int flag, cred_t *cred)
1581 {
1582 	gld_t	*gld = (gld_t *)q->q_ptr;
1583 	glddev_t *glddev = gld->gld_device;
1584 
1585 	ASSERT(q);
1586 	ASSERT(gld);
1587 
1588 #ifdef GLD_DEBUG
1589 	if (gld_debug & GLDPROT) {
1590 		cmn_err(CE_NOTE, "gld_close(%p, Style %d)",
1591 		    (void *)q, (gld->gld_style & 0x1) + 1);
1592 	}
1593 #endif
1594 
1595 	/* Hold all device streams lists still while we check for a macinfo */
1596 	mutex_enter(&glddev->gld_devlock);
1597 
1598 	if (gld->gld_mac_info != NULL) {
1599 		/* If there's a macinfo, block recv while we change state */
1600 		GLDM_LOCK(gld->gld_mac_info, RW_WRITER);
1601 		gld->gld_flags |= GLD_STR_CLOSING; /* no more rcv putnexts */
1602 		GLDM_UNLOCK(gld->gld_mac_info);
1603 	} else {
1604 		/* no mac DL_ATTACHED right now */
1605 		gld->gld_flags |= GLD_STR_CLOSING;
1606 	}
1607 
1608 	mutex_exit(&glddev->gld_devlock);
1609 
1610 	/*
1611 	 * qprocsoff before we call gld_unbind/gldunattach, so that
1612 	 * we know wsrv isn't in there trying to undo what we're doing.
1613 	 */
1614 	qprocsoff(q);
1615 
1616 	ASSERT(gld->gld_wput_count == 0);
1617 	gld->gld_wput_count = 0;	/* just in case */
1618 
1619 	if (gld->gld_state == DL_IDLE) {
1620 		/* Need to unbind */
1621 		ASSERT(gld->gld_mac_info != NULL);
1622 		(void) gld_unbind(WR(q), NULL);
1623 	}
1624 
1625 	if (gld->gld_state == DL_UNBOUND) {
1626 		/*
1627 		 * Need to unattach
1628 		 * For style 2 stream, gldunattach also
1629 		 * associate queue with NULL dip
1630 		 */
1631 		ASSERT(gld->gld_mac_info != NULL);
1632 		(void) gldunattach(WR(q), NULL);
1633 	}
1634 
1635 	/* disassociate the stream from the device */
1636 	q->q_ptr = WR(q)->q_ptr = NULL;
1637 
1638 	/*
1639 	 * Since we unattached above (if necessary), we know that we're
1640 	 * on the per-major list of unattached streams, rather than a
1641 	 * per-PPA list.  So we know we should hold the devlock.
1642 	 */
1643 	mutex_enter(&glddev->gld_devlock);
1644 	gldremque(gld);			/* remove from Style 2 list */
1645 	mutex_exit(&glddev->gld_devlock);
1646 
1647 	kmem_free(gld, sizeof (gld_t));
1648 
1649 	return (0);
1650 }
1651 
1652 /*
1653  * gld_rsrv (q)
1654  *	simple read service procedure
1655  *	purpose is to avoid the time it takes for packets
1656  *	to move through IP so we can get them off the board
1657  *	as fast as possible due to limited PC resources.
1658  *
1659  *	This is not normally used in the current implementation.  It
1660  *	can be selected with the undocumented property "fast_recv".
1661  *	If that property is set, gld_recv will send the packet
1662  *	upstream with a putq() rather than a putnext(), thus causing
1663  *	this routine to be scheduled.
1664  */
1665 int
1666 gld_rsrv(queue_t *q)
1667 {
1668 	mblk_t *mp;
1669 
1670 	while ((mp = getq(q)) != NULL) {
1671 		if (canputnext(q)) {
1672 			putnext(q, mp);
1673 		} else {
1674 			freemsg(mp);
1675 		}
1676 	}
1677 	return (0);
1678 }
1679 
1680 /*
1681  * gld_wput (q, mp)
1682  * general gld stream write put routine. Receives fastpath data from upper
1683  * modules and processes it immediately.  ioctl and M_PROTO/M_PCPROTO are
1684  * queued for later processing by the service procedure.
1685  */
1686 
1687 int
1688 gld_wput(queue_t *q, mblk_t *mp)
1689 {
1690 	gld_t  *gld = (gld_t *)(q->q_ptr);
1691 	int	rc;
1692 	boolean_t multidata = B_TRUE;
1693 
1694 #ifdef GLD_DEBUG
1695 	if (gld_debug & GLDTRACE)
1696 		cmn_err(CE_NOTE, "gld_wput(%p %p): type %x",
1697 		    (void *)q, (void *)mp, DB_TYPE(mp));
1698 #endif
1699 	switch (DB_TYPE(mp)) {
1700 
1701 	case M_DATA:
1702 		/* fast data / raw support */
1703 		/* we must be DL_ATTACHED and DL_BOUND to do this */
1704 		/* Tricky to access memory without taking the mutex */
1705 		if ((gld->gld_flags & (GLD_RAW | GLD_FAST)) == 0 ||
1706 		    gld->gld_state != DL_IDLE) {
1707 			merror(q, mp, EPROTO);
1708 			break;
1709 		}
1710 		multidata = B_FALSE;
1711 		/* LINTED: E_CASE_FALLTHRU */
1712 	case M_MULTIDATA:
1713 		/* Only call gld_start() directly if nothing queued ahead */
1714 		/* No guarantees about ordering with different threads */
1715 		if (q->q_first)
1716 			goto use_wsrv;
1717 
1718 		/*
1719 		 * This can happen if wsrv has taken off the last mblk but
1720 		 * is still processing it.
1721 		 */
1722 		membar_consumer();
1723 		if (gld->gld_in_wsrv)
1724 			goto use_wsrv;
1725 
1726 		/*
1727 		 * Keep a count of current wput calls to start.
1728 		 * Nonzero count delays any attempted DL_UNBIND.
1729 		 * See comments above gld_start().
1730 		 */
1731 		atomic_add_32((uint32_t *)&gld->gld_wput_count, 1);
1732 		membar_enter();
1733 
1734 		/* Recheck state now wput_count is set to prevent DL_UNBIND */
1735 		/* If this Q is in process of DL_UNBIND, don't call start */
1736 		if (gld->gld_state != DL_IDLE || gld->gld_in_unbind) {
1737 			/* Extremely unlikely */
1738 			atomic_add_32((uint32_t *)&gld->gld_wput_count, -1);
1739 			goto use_wsrv;
1740 		}
1741 
1742 		rc = (multidata) ? gld_start_mdt(q, mp, GLD_WPUT) :
1743 		    gld_start(q, mp, GLD_WPUT, UPRI(gld, mp->b_band));
1744 
1745 		/* Allow DL_UNBIND again */
1746 		membar_exit();
1747 		atomic_add_32((uint32_t *)&gld->gld_wput_count, -1);
1748 
1749 		if (rc == GLD_NORESOURCES)
1750 			qenable(q);
1751 		break;	/*  Done with this packet */
1752 
1753 use_wsrv:
1754 		/* Q not empty, in DL_DETACH, or start gave NORESOURCES */
1755 		(void) putq(q, mp);
1756 		qenable(q);
1757 		break;
1758 
1759 	case M_IOCTL:
1760 		/* ioctl relies on wsrv single threading per queue */
1761 		(void) putq(q, mp);
1762 		qenable(q);
1763 		break;
1764 
1765 	case M_CTL:
1766 		(void) putq(q, mp);
1767 		qenable(q);
1768 		break;
1769 
1770 	case M_FLUSH:		/* canonical flush handling */
1771 		/* XXX Should these be FLUSHALL? */
1772 		if (*mp->b_rptr & FLUSHW)
1773 			flushq(q, 0);
1774 		if (*mp->b_rptr & FLUSHR) {
1775 			flushq(RD(q), 0);
1776 			*mp->b_rptr &= ~FLUSHW;
1777 			qreply(q, mp);
1778 		} else
1779 			freemsg(mp);
1780 		break;
1781 
1782 	case M_PROTO:
1783 	case M_PCPROTO:
1784 		/* these rely on wsrv single threading per queue */
1785 		(void) putq(q, mp);
1786 		qenable(q);
1787 		break;
1788 
1789 	default:
1790 #ifdef GLD_DEBUG
1791 		if (gld_debug & GLDETRACE)
1792 			cmn_err(CE_WARN,
1793 			    "gld: Unexpected packet type from queue: 0x%x",
1794 			    DB_TYPE(mp));
1795 #endif
1796 		freemsg(mp);
1797 	}
1798 	return (0);
1799 }
1800 
1801 /*
1802  * gld_wsrv - Incoming messages are processed according to the DLPI protocol
1803  * specification.
1804  *
1805  * wsrv is single-threaded per Q.  We make use of this to avoid taking the
1806  * lock for reading data items that are only ever written by us.
1807  */
1808 
1809 int
1810 gld_wsrv(queue_t *q)
1811 {
1812 	mblk_t *mp;
1813 	gld_t *gld = (gld_t *)q->q_ptr;
1814 	gld_mac_info_t *macinfo;
1815 	union DL_primitives *prim;
1816 	int err;
1817 	boolean_t multidata;
1818 
1819 #ifdef GLD_DEBUG
1820 	if (gld_debug & GLDTRACE)
1821 		cmn_err(CE_NOTE, "gld_wsrv(%p)", (void *)q);
1822 #endif
1823 
1824 	ASSERT(!gld->gld_in_wsrv);
1825 
1826 	gld->gld_xwait = B_FALSE; /* We are now going to process this Q */
1827 
1828 	if (q->q_first == NULL)
1829 		return (0);
1830 
1831 	macinfo = gld->gld_mac_info;
1832 
1833 	/*
1834 	 * Help wput avoid a call to gld_start if there might be a message
1835 	 * previously queued by that thread being processed here.
1836 	 */
1837 	gld->gld_in_wsrv = B_TRUE;
1838 	membar_enter();
1839 
1840 	while ((mp = getq(q)) != NULL) {
1841 		switch (DB_TYPE(mp)) {
1842 		case M_DATA:
1843 		case M_MULTIDATA:
1844 			multidata = (DB_TYPE(mp) == M_MULTIDATA);
1845 
1846 			/*
1847 			 * retry of a previously processed UNITDATA_REQ
1848 			 * or is a RAW or FAST message from above.
1849 			 */
1850 			if (macinfo == NULL) {
1851 				/* No longer attached to a PPA, drop packet */
1852 				freemsg(mp);
1853 				break;
1854 			}
1855 
1856 			gld->gld_sched_ran = B_FALSE;
1857 			membar_enter();
1858 			err = (multidata) ? gld_start_mdt(q, mp, GLD_WSRV) :
1859 			    gld_start(q, mp, GLD_WSRV, UPRI(gld, mp->b_band));
1860 			if (err == GLD_NORESOURCES) {
1861 				/* gld_sched will qenable us later */
1862 				gld->gld_xwait = B_TRUE; /* want qenable */
1863 				membar_enter();
1864 				/*
1865 				 * v2:  we're not holding the lock; it's
1866 				 * possible that the driver could have already
1867 				 * called gld_sched (following up on its
1868 				 * return of GLD_NORESOURCES), before we got a
1869 				 * chance to do the putbq() and set gld_xwait.
1870 				 * So if we saw a call to gld_sched that
1871 				 * examined this queue, since our call to
1872 				 * gld_start() above, then it's possible we've
1873 				 * already seen the only call to gld_sched()
1874 				 * we're ever going to see.  So we better retry
1875 				 * transmitting this packet right now.
1876 				 */
1877 				if (gld->gld_sched_ran) {
1878 #ifdef GLD_DEBUG
1879 					if (gld_debug & GLDTRACE)
1880 						cmn_err(CE_NOTE, "gld_wsrv: "
1881 						    "sched was called");
1882 #endif
1883 					break;	/* try again right now */
1884 				}
1885 				gld->gld_in_wsrv = B_FALSE;
1886 				return (0);
1887 			}
1888 			break;
1889 
1890 		case M_IOCTL:
1891 			(void) gld_ioctl(q, mp);
1892 			break;
1893 
1894 		case M_CTL:
1895 			if (macinfo == NULL) {
1896 				freemsg(mp);
1897 				break;
1898 			}
1899 
1900 			if (macinfo->gldm_mctl != NULL) {
1901 				GLDM_LOCK(macinfo, RW_WRITER);
1902 				(void) (*macinfo->gldm_mctl) (macinfo, q, mp);
1903 				GLDM_UNLOCK(macinfo);
1904 			} else {
1905 				/* This driver doesn't recognize, just drop */
1906 				freemsg(mp);
1907 			}
1908 			break;
1909 
1910 		case M_PROTO:	/* Will be an DLPI message of some type */
1911 		case M_PCPROTO:
1912 			if ((err = gld_cmds(q, mp)) != GLDE_OK) {
1913 				if (err == GLDE_RETRY) {
1914 					gld->gld_in_wsrv = B_FALSE;
1915 					return (0); /* quit while we're ahead */
1916 				}
1917 				prim = (union DL_primitives *)mp->b_rptr;
1918 				dlerrorack(q, mp, prim->dl_primitive, err, 0);
1919 			}
1920 			break;
1921 
1922 		default:
1923 			/* This should never happen */
1924 #ifdef GLD_DEBUG
1925 			if (gld_debug & GLDERRS)
1926 				cmn_err(CE_WARN,
1927 				    "gld_wsrv: db_type(%x) not supported",
1928 				    mp->b_datap->db_type);
1929 #endif
1930 			freemsg(mp);	/* unknown types are discarded */
1931 			break;
1932 		}
1933 	}
1934 
1935 	membar_exit();
1936 	gld->gld_in_wsrv = B_FALSE;
1937 	return (0);
1938 }
1939 
1940 /*
1941  * gld_start() can get called from gld_wput(), gld_wsrv(), or gld_unitdata().
1942  *
1943  * We only come directly from wput() in the GLD_FAST (fastpath) or RAW case.
1944  *
1945  * In particular, we must avoid calling gld_precv*() if we came from wput().
1946  * gld_precv*() is where we, on the transmit side, loop back our outgoing
1947  * packets to the receive side if we are in physical promiscuous mode.
1948  * Since the receive side holds a lock across its call to the upstream
1949  * putnext, and that upstream module could well have looped back to our
1950  * wput() routine on the same thread, we cannot call gld_precv* from here
1951  * for fear of causing a recursive lock entry in our receive code.
1952  *
1953  * There is a problem here when coming from gld_wput().  While wput
1954  * only comes here if the queue is attached to a PPA and bound to a SAP
1955  * and there are no messages on the queue ahead of the M_DATA that could
1956  * change that, it is theoretically possible that another thread could
1957  * now wput a DL_UNBIND and a DL_DETACH message, and the wsrv() routine
1958  * could wake up and process them, before we finish processing this
1959  * send of the M_DATA.  This can only possibly happen on a Style 2 RAW or
1960  * FAST (fastpath) stream:  non RAW/FAST streams always go through wsrv(),
1961  * and Style 1 streams only DL_DETACH in the close routine, where
1962  * qprocsoff() protects us.  If this happens we could end up calling
1963  * gldm_send() after we have detached the stream and possibly called
1964  * gldm_stop().  Worse, once the number of attached streams goes to zero,
1965  * detach/unregister could be called, and the macinfo could go away entirely.
1966  *
1967  * No one has ever seen this happen.
1968  *
1969  * It is some trouble to fix this, and we would rather not add any mutex
1970  * logic into the wput() routine, which is supposed to be a "fast"
1971  * path.
1972  *
1973  * What I've done is use an atomic counter to keep a count of the number
1974  * of threads currently calling gld_start() from wput() on this stream.
1975  * If DL_DETACH sees this as nonzero, it putbqs the request back onto
1976  * the queue and qenables, hoping to have better luck next time.  Since
1977  * people shouldn't be trying to send after they've asked to DL_DETACH,
1978  * hopefully very soon all the wput=>start threads should have returned
1979  * and the DL_DETACH will succeed.  It's hard to test this since the odds
1980  * of the failure even trying to happen are so small.  I probably could
1981  * have ignored the whole issue and never been the worse for it.
1982  */
1983 static int
1984 gld_start(queue_t *q, mblk_t *mp, int caller, uint32_t upri)
1985 {
1986 	mblk_t *nmp;
1987 	gld_t *gld = (gld_t *)q->q_ptr;
1988 	gld_mac_info_t *macinfo;
1989 	gld_mac_pvt_t *mac_pvt;
1990 	int rc;
1991 	gld_interface_t *ifp;
1992 	pktinfo_t pktinfo;
1993 	uint32_t vtag;
1994 	gld_vlan_t *vlan;
1995 
1996 	ASSERT(DB_TYPE(mp) == M_DATA);
1997 	macinfo = gld->gld_mac_info;
1998 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
1999 	ifp = mac_pvt->interfacep;
2000 	vlan = (gld_vlan_t *)gld->gld_vlan;
2001 
2002 	if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_TX) != 0) {
2003 		freemsg(mp);
2004 #ifdef GLD_DEBUG
2005 		if (gld_debug & GLDERRS)
2006 			cmn_err(CE_WARN,
2007 			    "gld_start: failed to interpret outbound packet");
2008 #endif
2009 		vlan->gldv_stats->glds_xmtbadinterp++;
2010 		return (GLD_BADARG);
2011 	}
2012 
2013 	/*
2014 	 * We're not holding the lock for this check.  If the promiscuous
2015 	 * state is in flux it doesn't matter much if we get this wrong.
2016 	 */
2017 	if (mac_pvt->nprom > 0) {
2018 		/*
2019 		 * We want to loopback to the receive side, but to avoid
2020 		 * recursive lock entry:  if we came from wput(), which
2021 		 * could have looped back via IP from our own receive
2022 		 * interrupt thread, we decline this request.  wput()
2023 		 * will then queue the packet for wsrv().  This means
2024 		 * that when snoop is running we don't get the advantage
2025 		 * of the wput() multithreaded direct entry to the
2026 		 * driver's send routine.
2027 		 */
2028 		if (caller == GLD_WPUT) {
2029 			(void) putbq(q, mp);
2030 			return (GLD_NORESOURCES);
2031 		}
2032 		if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY)
2033 			nmp = dupmsg_noloan(mp);
2034 		else
2035 			nmp = dupmsg(mp);
2036 	} else
2037 		nmp = NULL;		/* we need no loopback */
2038 
2039 	vtag = GLD_MK_VTAG(vlan->gldv_ptag, upri);
2040 	if (ifp->hdr_size > 0 &&
2041 	    pktinfo.pktLen > ifp->hdr_size + (vtag == 0 ? 0 : VTAG_SIZE) +
2042 	    macinfo->gldm_maxpkt) {
2043 		freemsg(mp);	/* discard oversized outbound packet */
2044 		if (nmp)
2045 			freemsg(nmp);	/* free the duped message */
2046 #ifdef GLD_DEBUG
2047 		if (gld_debug & GLDERRS)
2048 			cmn_err(CE_WARN,
2049 			    "gld_start: oversize outbound packet, size %d,"
2050 			    "max %d", pktinfo.pktLen,
2051 			    ifp->hdr_size + macinfo->gldm_maxpkt);
2052 #endif
2053 		vlan->gldv_stats->glds_xmtbadinterp++;
2054 		return (GLD_BADARG);
2055 	}
2056 
2057 	rc = (*gld->gld_send)(macinfo, mp, vtag);
2058 
2059 	if (rc != GLD_SUCCESS) {
2060 		if (rc == GLD_NORESOURCES) {
2061 			vlan->gldv_stats->glds_xmtretry++;
2062 			(void) putbq(q, mp);
2063 		} else {
2064 			/* transmit error; drop the packet */
2065 			freemsg(mp);
2066 			/* We're supposed to count failed attempts as well */
2067 			UPDATE_STATS(vlan, pktinfo, 1);
2068 #ifdef GLD_DEBUG
2069 			if (gld_debug & GLDERRS)
2070 				cmn_err(CE_WARN,
2071 				    "gld_start: gldm_send failed %d", rc);
2072 #endif
2073 		}
2074 		if (nmp)
2075 			freemsg(nmp);	/* free the dupped message */
2076 		return (rc);
2077 	}
2078 
2079 	UPDATE_STATS(vlan, pktinfo, 1);
2080 
2081 	/*
2082 	 * Loopback case. The message needs to be returned back on
2083 	 * the read side. This would silently fail if the dumpmsg fails
2084 	 * above. This is probably OK, if there is no memory to dup the
2085 	 * block, then there isn't much we could do anyway.
2086 	 */
2087 	if (nmp) {
2088 		GLDM_LOCK(macinfo, RW_WRITER);
2089 		gld_precv(macinfo, vlan, nmp);
2090 		GLDM_UNLOCK(macinfo);
2091 	}
2092 
2093 	return (GLD_SUCCESS);
2094 }
2095 
2096 /*
2097  * With MDT V.2 a single message mp can have one header area and multiple
2098  * payload areas. A packet is described by dl_pkt_info, and each packet can
2099  * span multiple payload areas (currently with TCP, each packet will have one
2100  * header and at the most two payload areas). MACs might have a limit on the
2101  * number of payload segments (i.e. per packet scatter-gather limit), and
2102  * MDT V.2 has a way of specifying that with mdt_span_limit; the MAC driver
2103  * might also have a limit on the total number of payloads in a message, and
2104  * that is specified by mdt_max_pld.
2105  */
2106 static int
2107 gld_start_mdt(queue_t *q, mblk_t *mp, int caller)
2108 {
2109 	mblk_t *nextmp;
2110 	gld_t *gld = (gld_t *)q->q_ptr;
2111 	gld_mac_info_t *macinfo = gld->gld_mac_info;
2112 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2113 	int numpacks, mdtpacks;
2114 	gld_interface_t *ifp = mac_pvt->interfacep;
2115 	pktinfo_t pktinfo;
2116 	gld_vlan_t *vlan = (gld_vlan_t *)gld->gld_vlan;
2117 	boolean_t doloop = B_FALSE;
2118 	multidata_t *dlmdp;
2119 	pdescinfo_t pinfo;
2120 	pdesc_t *dl_pkt;
2121 	void *cookie;
2122 	uint_t totLen = 0;
2123 
2124 	ASSERT(DB_TYPE(mp) == M_MULTIDATA);
2125 
2126 	/*
2127 	 * We're not holding the lock for this check.  If the promiscuous
2128 	 * state is in flux it doesn't matter much if we get this wrong.
2129 	 */
2130 	if (mac_pvt->nprom > 0) {
2131 		/*
2132 		 * We want to loopback to the receive side, but to avoid
2133 		 * recursive lock entry:  if we came from wput(), which
2134 		 * could have looped back via IP from our own receive
2135 		 * interrupt thread, we decline this request.  wput()
2136 		 * will then queue the packet for wsrv().  This means
2137 		 * that when snoop is running we don't get the advantage
2138 		 * of the wput() multithreaded direct entry to the
2139 		 * driver's send routine.
2140 		 */
2141 		if (caller == GLD_WPUT) {
2142 			(void) putbq(q, mp);
2143 			return (GLD_NORESOURCES);
2144 		}
2145 		doloop = B_TRUE;
2146 
2147 		/*
2148 		 * unlike the M_DATA case, we don't have to call
2149 		 * dupmsg_noloan here because mmd_transform
2150 		 * (called by gld_precv_mdt) will make a copy of
2151 		 * each dblk.
2152 		 */
2153 	}
2154 
2155 	while (mp != NULL) {
2156 		/*
2157 		 * The lower layer driver only gets a single multidata
2158 		 * message; this also makes it easier to handle noresources.
2159 		 */
2160 		nextmp = mp->b_cont;
2161 		mp->b_cont = NULL;
2162 
2163 		/*
2164 		 * Get number of packets in this message; if nothing
2165 		 * to transmit, go to next message.
2166 		 */
2167 		dlmdp = mmd_getmultidata(mp);
2168 		if ((mdtpacks = (int)mmd_getcnt(dlmdp, NULL, NULL)) == 0) {
2169 			freemsg(mp);
2170 			mp = nextmp;
2171 			continue;
2172 		}
2173 
2174 		/*
2175 		 * Run interpreter to populate media specific pktinfo fields.
2176 		 * This collects per MDT message information like sap,
2177 		 * broad/multicast etc.
2178 		 */
2179 		(void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, &pktinfo,
2180 		    GLD_MDT_TX);
2181 
2182 		numpacks = (*macinfo->gldm_mdt_pre)(macinfo, mp, &cookie);
2183 
2184 		if (numpacks > 0) {
2185 			/*
2186 			 * Driver indicates it can transmit at least 1, and
2187 			 * possibly all, packets in MDT message.
2188 			 */
2189 			int count = numpacks;
2190 
2191 			for (dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo);
2192 			    (dl_pkt != NULL);
2193 			    dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo)) {
2194 				/*
2195 				 * Format this packet by adding link header and
2196 				 * adjusting pdescinfo to include it; get
2197 				 * packet length.
2198 				 */
2199 				(void) (*ifp->interpreter_mdt)(macinfo, NULL,
2200 				    &pinfo, &pktinfo, GLD_MDT_TXPKT);
2201 
2202 				totLen += pktinfo.pktLen;
2203 
2204 				/*
2205 				 * Loop back packet before handing to the
2206 				 * driver.
2207 				 */
2208 				if (doloop &&
2209 				    mmd_adjpdesc(dl_pkt, &pinfo) != NULL) {
2210 					GLDM_LOCK(macinfo, RW_WRITER);
2211 					gld_precv_mdt(macinfo, vlan, mp,
2212 					    dl_pkt, &pktinfo);
2213 					GLDM_UNLOCK(macinfo);
2214 				}
2215 
2216 				/*
2217 				 * And send off to driver.
2218 				 */
2219 				(*macinfo->gldm_mdt_send)(macinfo, cookie,
2220 				    &pinfo);
2221 
2222 				/*
2223 				 * Be careful not to invoke getnextpdesc if we
2224 				 * already sent the last packet, since driver
2225 				 * might have posted it to hardware causing a
2226 				 * completion and freemsg() so the MDT data
2227 				 * structures might not be valid anymore.
2228 				 */
2229 				if (--count == 0)
2230 					break;
2231 			}
2232 			(*macinfo->gldm_mdt_post)(macinfo, mp, cookie);
2233 			pktinfo.pktLen = totLen;
2234 			UPDATE_STATS(vlan, pktinfo, numpacks);
2235 
2236 			/*
2237 			 * In the noresources case (when driver indicates it
2238 			 * can not transmit all packets in the MDT message),
2239 			 * adjust to skip the first few packets on retrial.
2240 			 */
2241 			if (numpacks != mdtpacks) {
2242 				/*
2243 				 * Release already processed packet descriptors.
2244 				 */
2245 				for (count = 0; count < numpacks; count++) {
2246 					dl_pkt = mmd_getfirstpdesc(dlmdp,
2247 					    &pinfo);
2248 					mmd_rempdesc(dl_pkt);
2249 				}
2250 				vlan->gldv_stats->glds_xmtretry++;
2251 				mp->b_cont = nextmp;
2252 				(void) putbq(q, mp);
2253 				return (GLD_NORESOURCES);
2254 			}
2255 		} else if (numpacks == 0) {
2256 			/*
2257 			 * Driver indicates it can not transmit any packets
2258 			 * currently and will request retrial later.
2259 			 */
2260 			vlan->gldv_stats->glds_xmtretry++;
2261 			mp->b_cont = nextmp;
2262 			(void) putbq(q, mp);
2263 			return (GLD_NORESOURCES);
2264 		} else {
2265 			ASSERT(numpacks == -1);
2266 			/*
2267 			 * We're supposed to count failed attempts as well.
2268 			 */
2269 			dl_pkt = mmd_getfirstpdesc(dlmdp, &pinfo);
2270 			while (dl_pkt != NULL) {
2271 				/*
2272 				 * Call interpreter to determine total packet
2273 				 * bytes that are being dropped.
2274 				 */
2275 				(void) (*ifp->interpreter_mdt)(macinfo, NULL,
2276 				    &pinfo, &pktinfo, GLD_MDT_TXPKT);
2277 
2278 				totLen += pktinfo.pktLen;
2279 
2280 				dl_pkt = mmd_getnextpdesc(dl_pkt, &pinfo);
2281 			}
2282 			pktinfo.pktLen = totLen;
2283 			UPDATE_STATS(vlan, pktinfo, mdtpacks);
2284 
2285 			/*
2286 			 * Transmit error; drop the message, move on
2287 			 * to the next one.
2288 			 */
2289 			freemsg(mp);
2290 		}
2291 
2292 		/*
2293 		 * Process the next multidata block, if there is one.
2294 		 */
2295 		mp = nextmp;
2296 	}
2297 
2298 	return (GLD_SUCCESS);
2299 }
2300 
2301 /*
2302  * gld_intr (macinfo)
2303  */
2304 uint_t
2305 gld_intr(gld_mac_info_t *macinfo)
2306 {
2307 	ASSERT(macinfo != NULL);
2308 
2309 	if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
2310 		return (DDI_INTR_UNCLAIMED);
2311 
2312 	return ((*macinfo->gldm_intr)(macinfo));
2313 }
2314 
2315 /*
2316  * gld_sched (macinfo)
2317  *
2318  * This routine scans the streams that refer to a specific macinfo
2319  * structure and causes the STREAMS scheduler to try to run them if
2320  * they are marked as waiting for the transmit buffer.
2321  */
2322 void
2323 gld_sched(gld_mac_info_t *macinfo)
2324 {
2325 	gld_mac_pvt_t *mac_pvt;
2326 	gld_t *gld;
2327 	gld_vlan_t *vlan;
2328 	int i;
2329 
2330 	ASSERT(macinfo != NULL);
2331 
2332 	GLDM_LOCK(macinfo, RW_WRITER);
2333 
2334 	if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
2335 		/* We're probably being called from a leftover interrupt */
2336 		GLDM_UNLOCK(macinfo);
2337 		return;
2338 	}
2339 
2340 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2341 
2342 	for (i = 0; i < VLAN_HASHSZ; i++) {
2343 		for (vlan = mac_pvt->vlan_hash[i];
2344 		    vlan != NULL; vlan = vlan->gldv_next) {
2345 			for (gld = vlan->gldv_str_next;
2346 			    gld != (gld_t *)&vlan->gldv_str_next;
2347 			    gld = gld->gld_next) {
2348 				ASSERT(gld->gld_mac_info == macinfo);
2349 				gld->gld_sched_ran = B_TRUE;
2350 				membar_enter();
2351 				if (gld->gld_xwait) {
2352 					gld->gld_xwait = B_FALSE;
2353 					qenable(WR(gld->gld_qptr));
2354 				}
2355 			}
2356 		}
2357 	}
2358 
2359 	GLDM_UNLOCK(macinfo);
2360 }
2361 
2362 /*
2363  * gld_precv (macinfo, mp)
2364  * called from gld_start to loopback a packet when in promiscuous mode
2365  */
2366 static void
2367 gld_precv(gld_mac_info_t *macinfo, gld_vlan_t *vlan, mblk_t *mp)
2368 {
2369 	gld_mac_pvt_t *mac_pvt;
2370 	gld_interface_t *ifp;
2371 	pktinfo_t pktinfo;
2372 
2373 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
2374 
2375 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2376 	ifp = mac_pvt->interfacep;
2377 
2378 	/*
2379 	 * call the media specific packet interpreter routine
2380 	 */
2381 	if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RXLOOP) != 0) {
2382 		freemsg(mp);
2383 		BUMP(vlan->gldv_stats->glds_rcvbadinterp, 1);
2384 #ifdef GLD_DEBUG
2385 		if (gld_debug & GLDERRS)
2386 			cmn_err(CE_WARN,
2387 			    "gld_precv: interpreter failed");
2388 #endif
2389 		return;
2390 	}
2391 
2392 	gld_sendup(macinfo, vlan, &pktinfo, mp, gld_paccept);
2393 }
2394 
2395 /*
2396  * called from gld_start_mdt to loopback packet(s) when in promiscuous mode
2397  */
2398 static void
2399 gld_precv_mdt(gld_mac_info_t *macinfo, gld_vlan_t *vlan, mblk_t *mp,
2400     pdesc_t *dl_pkt, pktinfo_t *pktinfo)
2401 {
2402 	mblk_t *adjmp;
2403 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2404 	gld_interface_t *ifp = mac_pvt->interfacep;
2405 
2406 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
2407 
2408 	/*
2409 	 * Get source/destination.
2410 	 */
2411 	(void) (*ifp->interpreter_mdt)(macinfo, mp, NULL, pktinfo,
2412 	    GLD_MDT_RXLOOP);
2413 	if ((adjmp = mmd_transform(dl_pkt)) != NULL)
2414 		gld_sendup(macinfo, vlan, pktinfo, adjmp, gld_paccept);
2415 }
2416 
2417 /*
2418  * gld_recv (macinfo, mp)
2419  * called with an mac-level packet in a mblock; take the maclock,
2420  * try the ip4q and ip6q hack, and otherwise call gld_sendup.
2421  *
2422  * V0 drivers already are holding the mutex when they call us.
2423  */
2424 void
2425 gld_recv(gld_mac_info_t *macinfo, mblk_t *mp)
2426 {
2427 	gld_recv_tagged(macinfo, mp, VLAN_VTAG_NONE);
2428 }
2429 
2430 void
2431 gld_recv_tagged(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag)
2432 {
2433 	gld_mac_pvt_t *mac_pvt;
2434 	char pbuf[3*GLD_MAX_ADDRLEN];
2435 	pktinfo_t pktinfo;
2436 	gld_interface_t *ifp;
2437 	queue_t *ipq = NULL;
2438 	gld_vlan_t *vlan;
2439 	uint32_t vid;
2440 
2441 	ASSERT(macinfo != NULL);
2442 	ASSERT(mp->b_datap->db_ref);
2443 
2444 	GLDM_LOCK(macinfo, RW_READER);
2445 
2446 	if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
2447 		/* We're probably being called from a leftover interrupt */
2448 		freemsg(mp);
2449 		goto done;
2450 	}
2451 
2452 	vid = GLD_VTAG_VID(vtag);
2453 	if ((vlan = gld_find_vlan(macinfo, vid)) == NULL) {
2454 		freemsg(mp);
2455 		goto done;
2456 	}
2457 
2458 	/*
2459 	 * Check whether underlying media code supports the IPQ hack,
2460 	 * and if so, whether the interpreter can quickly parse the
2461 	 * packet to get some relevant parameters.
2462 	 */
2463 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
2464 	ifp = mac_pvt->interfacep;
2465 	if (((*ifp->interpreter)(macinfo, mp, &pktinfo,
2466 	    GLD_RXQUICK) == 0) && (vlan->gldv_ipq_flags == 0)) {
2467 		switch (pktinfo.ethertype) {
2468 		case ETHERTYPE_IP:
2469 			ipq = vlan->gldv_ipq;
2470 			break;
2471 		case ETHERTYPE_IPV6:
2472 			ipq = vlan->gldv_ipv6q;
2473 			break;
2474 		}
2475 	}
2476 
2477 	BUMP(vlan->gldv_stats->glds_bytercv64, pktinfo.pktLen);
2478 	BUMP(vlan->gldv_stats->glds_pktrcv64, 1);
2479 
2480 	/*
2481 	 * Special case for IP; we can simply do the putnext here, if:
2482 	 * o ipq != NULL, and therefore:
2483 	 * - the device type supports IPQ (ethernet and IPoIB);
2484 	 * - the interpreter could quickly parse the packet;
2485 	 * - there are no PROMISC_SAP streams (on this VLAN);
2486 	 * - there is one, and only one, IP stream bound (to this VLAN);
2487 	 * - that stream is a "fastpath" stream;
2488 	 * - the packet is of type ETHERTYPE_IP or ETHERTYPE_IPV6
2489 	 *
2490 	 * o the packet is specifically for me, and therefore:
2491 	 * - the packet is not multicast or broadcast (fastpath only
2492 	 *   wants unicast packets).
2493 	 *
2494 	 * o the stream is not asserting flow control.
2495 	 */
2496 	if (ipq != NULL &&
2497 	    pktinfo.isForMe &&
2498 	    canputnext(ipq)) {
2499 		/*
2500 		 * Skip the mac header. We know there is no LLC1/SNAP header
2501 		 * in this packet
2502 		 */
2503 		mp->b_rptr += pktinfo.macLen;
2504 		putnext(ipq, mp);
2505 		goto done;
2506 	}
2507 
2508 	/*
2509 	 * call the media specific packet interpreter routine
2510 	 */
2511 	if ((*ifp->interpreter)(macinfo, mp, &pktinfo, GLD_RX) != 0) {
2512 		BUMP(vlan->gldv_stats->glds_rcvbadinterp, 1);
2513 #ifdef GLD_DEBUG
2514 		if (gld_debug & GLDERRS)
2515 			cmn_err(CE_WARN,
2516 			    "gld_recv_tagged: interpreter failed");
2517 #endif
2518 		freemsg(mp);
2519 		goto done;
2520 	}
2521 
2522 	/*
2523 	 * This is safe even if vtag is VLAN_VTAG_NONE
2524 	 */
2525 
2526 	pktinfo.vid = vid;
2527 	pktinfo.cfi = GLD_VTAG_CFI(vtag);
2528 #ifdef GLD_DEBUG
2529 	if (pktinfo.cfi != VLAN_CFI_ETHER)
2530 		cmn_err(CE_WARN, "gld_recv_tagged: non-ETHER CFI");
2531 #endif
2532 	pktinfo.user_pri = GLD_VTAG_PRI(vtag);
2533 
2534 #ifdef GLD_DEBUG
2535 	if ((gld_debug & GLDRECV) &&
2536 	    (!(gld_debug & GLDNOBR) ||
2537 	    (!pktinfo.isBroadcast && !pktinfo.isMulticast))) {
2538 		char pbuf2[3*GLD_MAX_ADDRLEN];
2539 
2540 		cmn_err(CE_CONT, "gld_recv_tagged: machdr=<%s -> %s>\n",
2541 		    gld_macaddr_sprintf(pbuf, pktinfo.shost,
2542 		    macinfo->gldm_addrlen), gld_macaddr_sprintf(pbuf2,
2543 		    pktinfo.dhost, macinfo->gldm_addrlen));
2544 		cmn_err(CE_CONT, "gld_recv_tagged: VlanId %d UserPri %d\n",
2545 		    pktinfo.vid,
2546 		    pktinfo.user_pri);
2547 		cmn_err(CE_CONT, "gld_recv_tagged: ethertype: %4x Len: %4d "
2548 		    "Hdr: %d,%d isMulticast: %s\n",
2549 		    pktinfo.ethertype,
2550 		    pktinfo.pktLen,
2551 		    pktinfo.macLen,
2552 		    pktinfo.hdrLen,
2553 		    pktinfo.isMulticast ? "Y" : "N");
2554 	}
2555 #endif
2556 
2557 	gld_sendup(macinfo, vlan, &pktinfo, mp, gld_accept);
2558 
2559 done:
2560 	GLDM_UNLOCK(macinfo);
2561 }
2562 
2563 /* =================================================================== */
2564 /* receive group: called from gld_recv and gld_precv* with maclock held */
2565 /* =================================================================== */
2566 
2567 /*
2568  * gld_sendup (macinfo, mp)
2569  * called with an ethernet packet in a mblock; must decide whether
2570  * packet is for us and which streams to queue it to.
2571  */
2572 static void
2573 gld_sendup(gld_mac_info_t *macinfo, gld_vlan_t *vlan, pktinfo_t *pktinfo,
2574     mblk_t *mp, int (*acceptfunc)())
2575 {
2576 	gld_t *gld;
2577 	gld_t *fgld = NULL;
2578 	mblk_t *nmp;
2579 	void (*send)(queue_t *qp, mblk_t *mp);
2580 	int (*cansend)(queue_t *qp);
2581 
2582 #ifdef GLD_DEBUG
2583 	if (gld_debug & GLDTRACE)
2584 		cmn_err(CE_NOTE, "gld_sendup(%p, %p)", (void *)mp,
2585 		    (void *)macinfo);
2586 #endif
2587 
2588 	ASSERT(mp != NULL);
2589 	ASSERT(macinfo != NULL);
2590 	ASSERT(vlan != NULL);
2591 	ASSERT(pktinfo != NULL);
2592 	ASSERT(GLDM_LOCK_HELD(macinfo));
2593 
2594 	/*
2595 	 * The "fast" in "GLDOPT_FAST_RECV" refers to the speed at which
2596 	 * gld_recv returns to the caller's interrupt routine.  The total
2597 	 * network throughput would normally be lower when selecting this
2598 	 * option, because we putq the messages and process them later,
2599 	 * instead of sending them with putnext now.  Some time critical
2600 	 * device might need this, so it's here but undocumented.
2601 	 */
2602 	if (macinfo->gldm_options & GLDOPT_FAST_RECV) {
2603 		send = (void (*)(queue_t *, mblk_t *))putq;
2604 		cansend = canput;
2605 	} else {
2606 		send = (void (*)(queue_t *, mblk_t *))putnext;
2607 		cansend = canputnext;
2608 	}
2609 
2610 	/*
2611 	 * Search all the streams attached to this macinfo looking for
2612 	 * those eligible to receive the present packet.
2613 	 */
2614 	for (gld = vlan->gldv_str_next;
2615 	    gld != (gld_t *)&vlan->gldv_str_next; gld = gld->gld_next) {
2616 #ifdef GLD_VERBOSE_DEBUG
2617 		cmn_err(CE_NOTE, "gld_sendup: SAP: %4x QPTR: %p QSTATE: %s",
2618 		    gld->gld_sap, (void *)gld->gld_qptr,
2619 		    gld->gld_state == DL_IDLE ? "IDLE": "NOT IDLE");
2620 #endif
2621 		ASSERT(gld->gld_qptr != NULL);
2622 		ASSERT(gld->gld_state == DL_IDLE ||
2623 		    gld->gld_state == DL_UNBOUND);
2624 		ASSERT(gld->gld_mac_info == macinfo);
2625 		ASSERT(gld->gld_vlan == vlan);
2626 
2627 		if (gld->gld_state != DL_IDLE)
2628 			continue;	/* not eligible to receive */
2629 		if (gld->gld_flags & GLD_STR_CLOSING)
2630 			continue;	/* not eligible to receive */
2631 
2632 #ifdef GLD_DEBUG
2633 		if ((gld_debug & GLDRECV) &&
2634 		    (!(gld_debug & GLDNOBR) ||
2635 		    (!pktinfo->isBroadcast && !pktinfo->isMulticast)))
2636 			cmn_err(CE_NOTE,
2637 			    "gld_sendup: queue sap: %4x promis: %s %s %s",
2638 			    gld->gld_sap,
2639 			    gld->gld_flags & GLD_PROM_PHYS ? "phys " : "     ",
2640 			    gld->gld_flags & GLD_PROM_SAP  ? "sap  " : "     ",
2641 			    gld->gld_flags & GLD_PROM_MULT ? "multi" : "     ");
2642 #endif
2643 
2644 		/*
2645 		 * The accept function differs depending on whether this is
2646 		 * a packet that we received from the wire or a loopback.
2647 		 */
2648 		if ((*acceptfunc)(gld, pktinfo)) {
2649 			/* sap matches */
2650 			pktinfo->wasAccepted = 1;	/* known protocol */
2651 
2652 			if (!(*cansend)(gld->gld_qptr)) {
2653 				/*
2654 				 * Upper stream is not accepting messages, i.e.
2655 				 * it is flow controlled, therefore we will
2656 				 * forgo sending the message up this stream.
2657 				 */
2658 #ifdef GLD_DEBUG
2659 				if (gld_debug & GLDETRACE)
2660 					cmn_err(CE_WARN,
2661 					    "gld_sendup: canput failed");
2662 #endif
2663 				BUMP(vlan->gldv_stats->glds_blocked, 1);
2664 				qenable(gld->gld_qptr);
2665 				continue;
2666 			}
2667 
2668 			/*
2669 			 * we are trying to avoid an extra dumpmsg() here.
2670 			 * If this is the first eligible queue, remember the
2671 			 * queue and send up the message after the loop.
2672 			 */
2673 			if (!fgld) {
2674 				fgld = gld;
2675 				continue;
2676 			}
2677 
2678 			/* duplicate the packet for this stream */
2679 			nmp = dupmsg(mp);
2680 			if (nmp == NULL) {
2681 				BUMP(vlan->gldv_stats->glds_gldnorcvbuf, 1);
2682 #ifdef GLD_DEBUG
2683 				if (gld_debug & GLDERRS)
2684 					cmn_err(CE_WARN,
2685 					    "gld_sendup: dupmsg failed");
2686 #endif
2687 				break;	/* couldn't get resources; drop it */
2688 			}
2689 			/* pass the message up the stream */
2690 			gld_passon(gld, nmp, pktinfo, send);
2691 		}
2692 	}
2693 
2694 	ASSERT(mp);
2695 	/* send the original dup of the packet up the first stream found */
2696 	if (fgld)
2697 		gld_passon(fgld, mp, pktinfo, send);
2698 	else
2699 		freemsg(mp);	/* no streams matched */
2700 
2701 	/* We do not count looped back packets */
2702 	if (acceptfunc == gld_paccept)
2703 		return;		/* transmit loopback case */
2704 
2705 	if (pktinfo->isBroadcast)
2706 		BUMP(vlan->gldv_stats->glds_brdcstrcv, 1);
2707 	else if (pktinfo->isMulticast)
2708 		BUMP(vlan->gldv_stats->glds_multircv, 1);
2709 
2710 	/* No stream accepted this packet */
2711 	if (!pktinfo->wasAccepted)
2712 		BUMP(vlan->gldv_stats->glds_unknowns, 1);
2713 }
2714 
2715 /*
2716  * A packet matches a stream if:
2717  *     the stream accepts EtherType encoded packets and the type matches
2718  *  or the stream accepts LLC packets and the packet is an LLC packet
2719  */
2720 #define	MATCH(stream, pktinfo) \
2721 	((stream->gld_ethertype && stream->gld_sap == pktinfo->ethertype) || \
2722 	(!stream->gld_ethertype && pktinfo->isLLC))
2723 
2724 /*
2725  * This function validates a packet for sending up a particular
2726  * stream. The message header has been parsed and its characteristic
2727  * are recorded in the pktinfo data structure. The streams stack info
2728  * are presented in gld data structures.
2729  */
2730 static int
2731 gld_accept(gld_t *gld, pktinfo_t *pktinfo)
2732 {
2733 	/*
2734 	 * if there is no match do not bother checking further.
2735 	 */
2736 	if (!MATCH(gld, pktinfo) && !(gld->gld_flags & GLD_PROM_SAP))
2737 		return (0);
2738 
2739 	/*
2740 	 * We don't accept any packet from the hardware if we originated it.
2741 	 * (Contrast gld_paccept, the send-loopback accept function.)
2742 	 */
2743 	if (pktinfo->isLooped)
2744 		return (0);
2745 
2746 	/*
2747 	 * If the packet is broadcast or sent to us directly we will accept it.
2748 	 * Also we will accept multicast packets requested by the stream.
2749 	 */
2750 	if (pktinfo->isForMe || pktinfo->isBroadcast ||
2751 	    gld_mcmatch(gld, pktinfo))
2752 		return (1);
2753 
2754 	/*
2755 	 * Finally, accept anything else if we're in promiscuous mode
2756 	 */
2757 	if (gld->gld_flags & GLD_PROM_PHYS)
2758 		return (1);
2759 
2760 	return (0);
2761 }
2762 
2763 /*
2764  * Return TRUE if the given multicast address is one
2765  * of those that this particular Stream is interested in.
2766  */
2767 static int
2768 gld_mcmatch(gld_t *gld, pktinfo_t *pktinfo)
2769 {
2770 	/*
2771 	 * Return FALSE if not a multicast address.
2772 	 */
2773 	if (!pktinfo->isMulticast)
2774 		return (0);
2775 
2776 	/*
2777 	 * Check if all multicasts have been enabled for this Stream
2778 	 */
2779 	if (gld->gld_flags & GLD_PROM_MULT)
2780 		return (1);
2781 
2782 	/*
2783 	 * Return FALSE if no multicast addresses enabled for this Stream.
2784 	 */
2785 	if (!gld->gld_mcast)
2786 		return (0);
2787 
2788 	/*
2789 	 * Otherwise, look for it in the table.
2790 	 */
2791 	return (gld_multicast(pktinfo->dhost, gld));
2792 }
2793 
2794 /*
2795  * gld_multicast determines if the address is a multicast address for
2796  * this stream.
2797  */
2798 static int
2799 gld_multicast(unsigned char *macaddr, gld_t *gld)
2800 {
2801 	int i;
2802 
2803 	ASSERT(GLDM_LOCK_HELD(gld->gld_mac_info));
2804 
2805 	if (!gld->gld_mcast)
2806 		return (0);
2807 
2808 	for (i = 0; i < gld->gld_multicnt; i++) {
2809 		if (gld->gld_mcast[i]) {
2810 			ASSERT(gld->gld_mcast[i]->gldm_refcnt);
2811 			if (mac_eq(gld->gld_mcast[i]->gldm_addr, macaddr,
2812 			    gld->gld_mac_info->gldm_addrlen))
2813 				return (1);
2814 		}
2815 	}
2816 
2817 	return (0);
2818 }
2819 
2820 /*
2821  * accept function for looped back packets
2822  */
2823 static int
2824 gld_paccept(gld_t *gld, pktinfo_t *pktinfo)
2825 {
2826 	return (gld->gld_flags & GLD_PROM_PHYS &&
2827 	    (MATCH(gld, pktinfo) || gld->gld_flags & GLD_PROM_SAP));
2828 }
2829 
2830 static void
2831 gld_passon(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo,
2832 	void (*send)(queue_t *qp, mblk_t *mp))
2833 {
2834 	int skiplen;
2835 
2836 #ifdef GLD_DEBUG
2837 	if (gld_debug & GLDTRACE)
2838 		cmn_err(CE_NOTE, "gld_passon(%p, %p, %p)", (void *)gld,
2839 		    (void *)mp, (void *)pktinfo);
2840 
2841 	if ((gld_debug & GLDRECV) && (!(gld_debug & GLDNOBR) ||
2842 	    (!pktinfo->isBroadcast && !pktinfo->isMulticast)))
2843 		cmn_err(CE_NOTE, "gld_passon: q: %p mblk: %p minor: %d sap: %x",
2844 		    (void *)gld->gld_qptr->q_next, (void *)mp, gld->gld_minor,
2845 		    gld->gld_sap);
2846 #endif
2847 
2848 	/*
2849 	 * Figure out how much of the packet header to throw away.
2850 	 *
2851 	 * RAW streams expect to see the whole packet.
2852 	 *
2853 	 * Other streams expect to see the packet with the MAC header
2854 	 * removed.
2855 	 *
2856 	 * Normal DLPI (non RAW/FAST) streams also want the
2857 	 * DL_UNITDATA_IND M_PROTO message block prepended to the M_DATA.
2858 	 */
2859 	if (gld->gld_flags & GLD_RAW) {
2860 		skiplen = 0;
2861 	} else {
2862 		skiplen = pktinfo->macLen;		/* skip mac header */
2863 		if (gld->gld_ethertype)
2864 			skiplen += pktinfo->hdrLen;	/* skip any extra */
2865 	}
2866 
2867 	if (skiplen >= pktinfo->pktLen) {
2868 		/*
2869 		 * If the interpreter did its job right, then it cannot be
2870 		 * asking us to skip more bytes than are in the packet!
2871 		 * However, there could be zero data bytes left after the
2872 		 * amount to skip.  DLPI specifies that passed M_DATA blocks
2873 		 * should contain at least one byte of data, so if we have
2874 		 * none we just drop it.
2875 		 */
2876 		ASSERT(!(skiplen > pktinfo->pktLen));
2877 		freemsg(mp);
2878 		return;
2879 	}
2880 
2881 	/*
2882 	 * Skip over the header(s), taking care to possibly handle message
2883 	 * fragments shorter than the amount we need to skip.  Hopefully
2884 	 * the driver will put the entire packet, or at least the entire
2885 	 * header, into a single message block.  But we handle it if not.
2886 	 */
2887 	while (skiplen >= MBLKL(mp)) {
2888 		mblk_t *tmp = mp;
2889 		skiplen -= MBLKL(mp);
2890 		mp = mp->b_cont;
2891 		ASSERT(mp != NULL);	/* because skiplen < pktinfo->pktLen */
2892 		freeb(tmp);
2893 	}
2894 	mp->b_rptr += skiplen;
2895 
2896 	/* Add M_PROTO if necessary, and pass upstream */
2897 	if (((gld->gld_flags & GLD_FAST) && !pktinfo->isMulticast &&
2898 	    !pktinfo->isBroadcast) || (gld->gld_flags & GLD_RAW)) {
2899 		/* RAW/FAST: just send up the M_DATA */
2900 		(*send)(gld->gld_qptr, mp);
2901 	} else {
2902 		/* everybody else wants to see a unitdata_ind structure */
2903 		mp = gld_addudind(gld, mp, pktinfo);
2904 		if (mp)
2905 			(*send)(gld->gld_qptr, mp);
2906 		/* if it failed, gld_addudind already bumped statistic */
2907 	}
2908 }
2909 
2910 /*
2911  * gld_addudind(gld, mp, pktinfo)
2912  * format a DL_UNITDATA_IND message to be sent upstream to the user
2913  */
2914 static mblk_t *
2915 gld_addudind(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo)
2916 {
2917 	gld_mac_info_t		*macinfo = gld->gld_mac_info;
2918 	gld_vlan_t		*vlan = (gld_vlan_t *)gld->gld_vlan;
2919 	dl_unitdata_ind_t	*dludindp;
2920 	mblk_t			*nmp;
2921 	int			size;
2922 	int			type;
2923 
2924 #ifdef GLD_DEBUG
2925 	if (gld_debug & GLDTRACE)
2926 		cmn_err(CE_NOTE, "gld_addudind(%p, %p, %p)", (void *)gld,
2927 		    (void *)mp, (void *)pktinfo);
2928 #endif
2929 	ASSERT(macinfo != NULL);
2930 
2931 	/*
2932 	 * Allocate the DL_UNITDATA_IND M_PROTO header, if allocation fails
2933 	 * might as well discard since we can't go further
2934 	 */
2935 	size = sizeof (dl_unitdata_ind_t) +
2936 	    2 * (macinfo->gldm_addrlen + abs(macinfo->gldm_saplen));
2937 	if ((nmp = allocb(size, BPRI_MED)) == NULL) {
2938 		freemsg(mp);
2939 		BUMP(vlan->gldv_stats->glds_gldnorcvbuf, 1);
2940 #ifdef GLD_DEBUG
2941 		if (gld_debug & GLDERRS)
2942 			cmn_err(CE_WARN,
2943 			    "gld_addudind: allocb failed");
2944 #endif
2945 		return ((mblk_t *)NULL);
2946 	}
2947 	DB_TYPE(nmp) = M_PROTO;
2948 	nmp->b_rptr = nmp->b_datap->db_lim - size;
2949 
2950 	type = (gld->gld_ethertype) ? pktinfo->ethertype : 0;
2951 
2952 	/*
2953 	 * now setup the DL_UNITDATA_IND header
2954 	 *
2955 	 * XXX This looks broken if the saps aren't two bytes.
2956 	 */
2957 	dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
2958 	dludindp->dl_primitive = DL_UNITDATA_IND;
2959 	dludindp->dl_src_addr_length =
2960 	    dludindp->dl_dest_addr_length = macinfo->gldm_addrlen +
2961 					abs(macinfo->gldm_saplen);
2962 	dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
2963 	dludindp->dl_src_addr_offset = dludindp->dl_dest_addr_offset +
2964 					dludindp->dl_dest_addr_length;
2965 
2966 	dludindp->dl_group_address = (pktinfo->isMulticast ||
2967 					pktinfo->isBroadcast);
2968 
2969 	nmp->b_wptr = nmp->b_rptr + dludindp->dl_dest_addr_offset;
2970 
2971 	mac_copy(pktinfo->dhost, nmp->b_wptr, macinfo->gldm_addrlen);
2972 	nmp->b_wptr += macinfo->gldm_addrlen;
2973 
2974 	ASSERT(macinfo->gldm_saplen == -2);	/* XXX following code assumes */
2975 	*(ushort_t *)(nmp->b_wptr) = type;
2976 	nmp->b_wptr += abs(macinfo->gldm_saplen);
2977 
2978 	ASSERT(nmp->b_wptr == nmp->b_rptr + dludindp->dl_src_addr_offset);
2979 
2980 	mac_copy(pktinfo->shost, nmp->b_wptr, macinfo->gldm_addrlen);
2981 	nmp->b_wptr += macinfo->gldm_addrlen;
2982 
2983 	*(ushort_t *)(nmp->b_wptr) = type;
2984 	nmp->b_wptr += abs(macinfo->gldm_saplen);
2985 
2986 	if (pktinfo->nosource)
2987 		dludindp->dl_src_addr_offset = dludindp->dl_src_addr_length = 0;
2988 	linkb(nmp, mp);
2989 	return (nmp);
2990 }
2991 
2992 /* ======================================================= */
2993 /* wsrv group: called from wsrv, single threaded per queue */
2994 /* ======================================================= */
2995 
2996 /*
2997  * We go to some trouble to avoid taking the same lock during normal
2998  * transmit processing as we do during normal receive processing.
2999  *
3000  * Elements of the per-instance macinfo and per-stream gld_t structures
3001  * are for the most part protected by the GLDM_LOCK rwlock/mutex.
3002  * (Elements of the gld_mac_pvt_t structure are considered part of the
3003  * macinfo structure for purposes of this discussion).
3004  *
3005  * However, it is more complicated than that:
3006  *
3007  *	Elements of the macinfo structure that are set before the macinfo
3008  *	structure is added to its device list by gld_register(), and never
3009  *	thereafter modified, are accessed without requiring taking the lock.
3010  *	A similar rule applies to those elements of the gld_t structure that
3011  *	are written by gld_open() before the stream is added to any list.
3012  *
3013  *	Most other elements of the macinfo structure may only be read or
3014  *	written while holding the maclock.
3015  *
3016  *	Most writable elements of the gld_t structure are written only
3017  *	within the single-threaded domain of wsrv() and subsidiaries.
3018  *	(This domain includes open/close while qprocs are not on.)
3019  *	The maclock need not be taken while within that domain
3020  *	simply to read those elements.  Writing to them, even within
3021  *	that domain, or reading from it outside that domain, requires
3022  *	holding the maclock.  Exception:  if the stream is not
3023  *	presently attached to a PPA, there is no associated macinfo,
3024  *	and no maclock need be taken.
3025  *
3026  *	The curr_macaddr element of the mac private structure is also
3027  *      protected by the GLDM_LOCK rwlock/mutex, like most other members
3028  *      of that structure. However, there are a few instances in the
3029  *      transmit path where we choose to forgo lock protection when
3030  *      reading this variable. This is to avoid lock contention between
3031  *      threads executing the DL_UNITDATA_REQ case and receive threads.
3032  *      In doing so we will take a small risk or a few corrupted packets
3033  *      during the short an rare times when someone is changing the interface's
3034  *      physical address. We consider the small cost in this rare case to be
3035  *      worth the benefit of reduced lock contention under normal operating
3036  *      conditions. The risk/cost is small because:
3037  *          1. there is no guarantee at this layer of uncorrupted delivery.
3038  *          2. the physaddr doesn't change very often - no performance hit.
3039  *          3. if the physaddr changes, other stuff is going to be screwed
3040  *             up for a while anyway, while other sites refigure ARP, etc.,
3041  *             so losing a couple of packets is the least of our worries.
3042  *
3043  *	The list of streams associated with a macinfo is protected by
3044  *	two locks:  the per-macinfo maclock, and the per-major-device
3045  *	gld_devlock.  Both must be held to modify the list, but either
3046  *	may be held to protect the list during reading/traversing.  This
3047  *	allows independent locking for multiple instances in the receive
3048  *	path (using macinfo), while facilitating routines that must search
3049  *	the entire set of streams associated with a major device, such as
3050  *	gld_findminor(), gld_finddevinfo(), close().  The "nstreams"
3051  *	macinfo	element, and the gld_mac_info gld_t element, are similarly
3052  *	protected, since they change at exactly the same time macinfo
3053  *	streams list does.
3054  *
3055  *	The list of macinfo structures associated with a major device
3056  *	structure is protected by the gld_devlock, as is the per-major
3057  *	list of Style 2 streams in the DL_UNATTACHED state.
3058  *
3059  *	The list of major devices is kept on a module-global list
3060  *	gld_device_list, which has its own lock to protect the list.
3061  *
3062  *	When it is necessary to hold more than one lock at a time, they
3063  *	are acquired in this "outside in" order:
3064  *		gld_device_list.gld_devlock
3065  *		glddev->gld_devlock
3066  *		GLDM_LOCK(macinfo)
3067  *
3068  *	Finally, there are some "volatile" elements of the gld_t structure
3069  *	used for synchronization between various routines that don't share
3070  *	the same mutexes.  See the routines for details.  These are:
3071  *		gld_xwait	between gld_wsrv() and gld_sched()
3072  *		gld_sched_ran	between gld_wsrv() and gld_sched()
3073  *		gld_in_unbind	between gld_wput() and wsrv's gld_unbind()
3074  *		gld_wput_count	between gld_wput() and wsrv's gld_unbind()
3075  *		gld_in_wsrv	between gld_wput() and gld_wsrv()
3076  *				(used in conjunction with q->q_first)
3077  */
3078 
3079 /*
3080  * gld_ioctl (q, mp)
3081  * handles all ioctl requests passed downstream. This routine is
3082  * passed a pointer to the message block with the ioctl request in it, and a
3083  * pointer to the queue so it can respond to the ioctl request with an ack.
3084  */
3085 int
3086 gld_ioctl(queue_t *q, mblk_t *mp)
3087 {
3088 	struct iocblk *iocp;
3089 	gld_t *gld;
3090 	gld_mac_info_t *macinfo;
3091 
3092 #ifdef GLD_DEBUG
3093 	if (gld_debug & GLDTRACE)
3094 		cmn_err(CE_NOTE, "gld_ioctl(%p %p)", (void *)q, (void *)mp);
3095 #endif
3096 	gld = (gld_t *)q->q_ptr;
3097 	iocp = (struct iocblk *)mp->b_rptr;
3098 	switch (iocp->ioc_cmd) {
3099 	case DLIOCRAW:		/* raw M_DATA mode */
3100 		gld->gld_flags |= GLD_RAW;
3101 		DB_TYPE(mp) = M_IOCACK;
3102 		qreply(q, mp);
3103 		break;
3104 
3105 	case DL_IOC_HDR_INFO:	/* fastpath */
3106 		if (gld_global_options & GLD_OPT_NO_FASTPATH) {
3107 			miocnak(q, mp, 0, EINVAL);
3108 			break;
3109 		}
3110 		gld_fastpath(gld, q, mp);
3111 		break;
3112 
3113 	default:
3114 		macinfo	 = gld->gld_mac_info;
3115 		if (macinfo == NULL || macinfo->gldm_ioctl == NULL) {
3116 			miocnak(q, mp, 0, EINVAL);
3117 			break;
3118 		}
3119 
3120 		GLDM_LOCK(macinfo, RW_WRITER);
3121 		(void) (*macinfo->gldm_ioctl) (macinfo, q, mp);
3122 		GLDM_UNLOCK(macinfo);
3123 		break;
3124 	}
3125 	return (0);
3126 }
3127 
3128 /*
3129  * Since the rules for "fastpath" mode don't seem to be documented
3130  * anywhere, I will describe GLD's rules for fastpath users here:
3131  *
3132  * Once in this mode you remain there until close.
3133  * If you unbind/rebind you should get a new header using DL_IOC_HDR_INFO.
3134  * You must be bound (DL_IDLE) to transmit.
3135  * There are other rules not listed above.
3136  */
3137 static void
3138 gld_fastpath(gld_t *gld, queue_t *q, mblk_t *mp)
3139 {
3140 	gld_interface_t *ifp;
3141 	gld_mac_info_t *macinfo;
3142 	dl_unitdata_req_t *dludp;
3143 	mblk_t *nmp;
3144 	t_scalar_t off, len;
3145 	uint_t maclen;
3146 	int error;
3147 	gld_vlan_t *vlan;
3148 
3149 	if (gld->gld_state != DL_IDLE) {
3150 		miocnak(q, mp, 0, EINVAL);
3151 		return;
3152 	}
3153 
3154 	macinfo = gld->gld_mac_info;
3155 	ASSERT(macinfo != NULL);
3156 	maclen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen);
3157 
3158 	error = miocpullup(mp, sizeof (dl_unitdata_req_t) + maclen);
3159 	if (error != 0) {
3160 		miocnak(q, mp, 0, error);
3161 		return;
3162 	}
3163 
3164 	dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
3165 	off = dludp->dl_dest_addr_offset;
3166 	len = dludp->dl_dest_addr_length;
3167 	if (dludp->dl_primitive != DL_UNITDATA_REQ ||
3168 	    !MBLKIN(mp->b_cont, off, len) || len != maclen) {
3169 		miocnak(q, mp, 0, EINVAL);
3170 		return;
3171 	}
3172 
3173 	/*
3174 	 * We take his fastpath request as a declaration that he will accept
3175 	 * M_DATA messages from us, whether or not we are willing to accept
3176 	 * them from him.  This allows us to have fastpath in one direction
3177 	 * (flow upstream) even on media with Source Routing, where we are
3178 	 * unable to provide a fixed MAC header to be prepended to downstream
3179 	 * flowing packets.  So we set GLD_FAST whether or not we decide to
3180 	 * allow him to send M_DATA down to us.
3181 	 */
3182 	GLDM_LOCK(macinfo, RW_WRITER);
3183 	gld->gld_flags |= GLD_FAST;
3184 	vlan = (gld_vlan_t *)gld->gld_vlan;
3185 	vlan->gldv_ipq_flags &= ~IPQ_DISABLED;
3186 	GLDM_UNLOCK(macinfo);
3187 
3188 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
3189 
3190 	/* This will fail for Source Routing media */
3191 	/* Also on Ethernet on 802.2 SAPs */
3192 	if ((nmp = (*ifp->mkfastpath)(gld, mp)) == NULL) {
3193 		miocnak(q, mp, 0, ENOMEM);
3194 		return;
3195 	}
3196 
3197 	/*
3198 	 * Link new mblk in after the "request" mblks.
3199 	 */
3200 	linkb(mp, nmp);
3201 	miocack(q, mp, msgdsize(mp->b_cont), 0);
3202 }
3203 
3204 /*
3205  * gld_cmds (q, mp)
3206  *	process the DL commands as defined in dlpi.h
3207  *	note that the primitives return status which is passed back
3208  *	to the service procedure.  If the value is GLDE_RETRY, then
3209  *	it is assumed that processing must stop and the primitive has
3210  *	been put back onto the queue.  If the value is any other error,
3211  *	then an error ack is generated by the service procedure.
3212  */
3213 static int
3214 gld_cmds(queue_t *q, mblk_t *mp)
3215 {
3216 	union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr;
3217 	gld_t *gld = (gld_t *)(q->q_ptr);
3218 	int result = DL_BADPRIM;
3219 	int mblkl = MBLKL(mp);
3220 	t_uscalar_t dlreq;
3221 
3222 	/* Make sure we have at least dlp->dl_primitive */
3223 	if (mblkl < sizeof (dlp->dl_primitive))
3224 		return (DL_BADPRIM);
3225 
3226 	dlreq = dlp->dl_primitive;
3227 #ifdef	GLD_DEBUG
3228 	if (gld_debug & GLDTRACE)
3229 		cmn_err(CE_NOTE,
3230 		    "gld_cmds(%p, %p):dlp=%p, dlp->dl_primitive=%d",
3231 		    (void *)q, (void *)mp, (void *)dlp, dlreq);
3232 #endif
3233 
3234 	switch (dlreq) {
3235 	case DL_UDQOS_REQ:
3236 		if (mblkl < DL_UDQOS_REQ_SIZE)
3237 			break;
3238 		result = gld_udqos(q, mp);
3239 		break;
3240 
3241 	case DL_BIND_REQ:
3242 		if (mblkl < DL_BIND_REQ_SIZE)
3243 			break;
3244 		result = gld_bind(q, mp);
3245 		break;
3246 
3247 	case DL_UNBIND_REQ:
3248 		if (mblkl < DL_UNBIND_REQ_SIZE)
3249 			break;
3250 		result = gld_unbind(q, mp);
3251 		break;
3252 
3253 	case DL_UNITDATA_REQ:
3254 		if (mblkl < DL_UNITDATA_REQ_SIZE)
3255 			break;
3256 		result = gld_unitdata(q, mp);
3257 		break;
3258 
3259 	case DL_INFO_REQ:
3260 		if (mblkl < DL_INFO_REQ_SIZE)
3261 			break;
3262 		result = gld_inforeq(q, mp);
3263 		break;
3264 
3265 	case DL_ATTACH_REQ:
3266 		if (mblkl < DL_ATTACH_REQ_SIZE)
3267 			break;
3268 		if (gld->gld_style == DL_STYLE2)
3269 			result = gldattach(q, mp);
3270 		else
3271 			result = DL_NOTSUPPORTED;
3272 		break;
3273 
3274 	case DL_DETACH_REQ:
3275 		if (mblkl < DL_DETACH_REQ_SIZE)
3276 			break;
3277 		if (gld->gld_style == DL_STYLE2)
3278 			result = gldunattach(q, mp);
3279 		else
3280 			result = DL_NOTSUPPORTED;
3281 		break;
3282 
3283 	case DL_ENABMULTI_REQ:
3284 		if (mblkl < DL_ENABMULTI_REQ_SIZE)
3285 			break;
3286 		result = gld_enable_multi(q, mp);
3287 		break;
3288 
3289 	case DL_DISABMULTI_REQ:
3290 		if (mblkl < DL_DISABMULTI_REQ_SIZE)
3291 			break;
3292 		result = gld_disable_multi(q, mp);
3293 		break;
3294 
3295 	case DL_PHYS_ADDR_REQ:
3296 		if (mblkl < DL_PHYS_ADDR_REQ_SIZE)
3297 			break;
3298 		result = gld_physaddr(q, mp);
3299 		break;
3300 
3301 	case DL_SET_PHYS_ADDR_REQ:
3302 		if (mblkl < DL_SET_PHYS_ADDR_REQ_SIZE)
3303 			break;
3304 		result = gld_setaddr(q, mp);
3305 		break;
3306 
3307 	case DL_PROMISCON_REQ:
3308 		if (mblkl < DL_PROMISCON_REQ_SIZE)
3309 			break;
3310 		result = gld_promisc(q, mp, dlreq, B_TRUE);
3311 		break;
3312 
3313 	case DL_PROMISCOFF_REQ:
3314 		if (mblkl < DL_PROMISCOFF_REQ_SIZE)
3315 			break;
3316 		result = gld_promisc(q, mp, dlreq, B_FALSE);
3317 		break;
3318 
3319 	case DL_GET_STATISTICS_REQ:
3320 		if (mblkl < DL_GET_STATISTICS_REQ_SIZE)
3321 			break;
3322 		result = gld_get_statistics(q, mp);
3323 		break;
3324 
3325 	case DL_CAPABILITY_REQ:
3326 		if (mblkl < DL_CAPABILITY_REQ_SIZE)
3327 			break;
3328 		result = gld_cap(q, mp);
3329 		break;
3330 
3331 	case DL_NOTIFY_REQ:
3332 		if (mblkl < DL_NOTIFY_REQ_SIZE)
3333 			break;
3334 		result = gld_notify_req(q, mp);
3335 		break;
3336 
3337 	case DL_XID_REQ:
3338 	case DL_XID_RES:
3339 	case DL_TEST_REQ:
3340 	case DL_TEST_RES:
3341 	case DL_CONTROL_REQ:
3342 	case DL_PASSIVE_REQ:
3343 		result = DL_NOTSUPPORTED;
3344 		break;
3345 
3346 	default:
3347 #ifdef	GLD_DEBUG
3348 		if (gld_debug & GLDERRS)
3349 			cmn_err(CE_WARN,
3350 			    "gld_cmds: unknown M_PROTO message: %d",
3351 			    dlreq);
3352 #endif
3353 		result = DL_BADPRIM;
3354 	}
3355 
3356 	return (result);
3357 }
3358 
3359 static int
3360 gld_cap(queue_t *q, mblk_t *mp)
3361 {
3362 	gld_t *gld = (gld_t *)q->q_ptr;
3363 	dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr;
3364 
3365 	if (gld->gld_state == DL_UNATTACHED)
3366 		return (DL_OUTSTATE);
3367 
3368 	if (dlp->dl_sub_length == 0)
3369 		return (gld_cap_ack(q, mp));
3370 
3371 	return (gld_cap_enable(q, mp));
3372 }
3373 
3374 static int
3375 gld_cap_ack(queue_t *q, mblk_t *mp)
3376 {
3377 	gld_t *gld = (gld_t *)q->q_ptr;
3378 	gld_mac_info_t *macinfo = gld->gld_mac_info;
3379 	gld_interface_t *ifp;
3380 	dl_capability_ack_t *dlap;
3381 	dl_capability_sub_t *dlsp;
3382 	size_t size = sizeof (dl_capability_ack_t);
3383 	size_t subsize = 0;
3384 
3385 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
3386 
3387 	if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY)
3388 		subsize += sizeof (dl_capability_sub_t) +
3389 		    sizeof (dl_capab_hcksum_t);
3390 	if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY)
3391 		subsize += sizeof (dl_capability_sub_t) +
3392 		    sizeof (dl_capab_zerocopy_t);
3393 	if (macinfo->gldm_options & GLDOPT_MDT)
3394 		subsize += (sizeof (dl_capability_sub_t) +
3395 		    sizeof (dl_capab_mdt_t));
3396 
3397 	if ((mp = mexchange(q, mp, size + subsize, M_PROTO,
3398 	    DL_CAPABILITY_ACK)) == NULL)
3399 		return (GLDE_OK);
3400 
3401 	dlap = (dl_capability_ack_t *)mp->b_rptr;
3402 	dlap->dl_sub_offset = 0;
3403 	if ((dlap->dl_sub_length = subsize) != 0)
3404 		dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
3405 	dlsp = (dl_capability_sub_t *)&dlap[1];
3406 
3407 	if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_ANY) {
3408 		dl_capab_hcksum_t *dlhp = (dl_capab_hcksum_t *)&dlsp[1];
3409 
3410 		dlsp->dl_cap = DL_CAPAB_HCKSUM;
3411 		dlsp->dl_length = sizeof (dl_capab_hcksum_t);
3412 
3413 		dlhp->hcksum_version = HCKSUM_VERSION_1;
3414 
3415 		dlhp->hcksum_txflags = 0;
3416 		if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_PARTIAL)
3417 			dlhp->hcksum_txflags |= HCKSUM_INET_PARTIAL;
3418 		if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V4)
3419 			dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V4;
3420 		if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_FULL_V6)
3421 			dlhp->hcksum_txflags |= HCKSUM_INET_FULL_V6;
3422 		if (macinfo->gldm_capabilities & GLD_CAP_CKSUM_IPHDR)
3423 			dlhp->hcksum_txflags |= HCKSUM_IPHDRCKSUM;
3424 
3425 		dlcapabsetqid(&(dlhp->hcksum_mid), RD(q));
3426 		dlsp = (dl_capability_sub_t *)&dlhp[1];
3427 	}
3428 
3429 	if (macinfo->gldm_capabilities & GLD_CAP_ZEROCOPY) {
3430 		dl_capab_zerocopy_t *dlzp = (dl_capab_zerocopy_t *)&dlsp[1];
3431 
3432 		dlsp->dl_cap = DL_CAPAB_ZEROCOPY;
3433 		dlsp->dl_length = sizeof (dl_capab_zerocopy_t);
3434 		dlzp->zerocopy_version = ZEROCOPY_VERSION_1;
3435 		dlzp->zerocopy_flags = DL_CAPAB_VMSAFE_MEM;
3436 
3437 		dlcapabsetqid(&(dlzp->zerocopy_mid), RD(q));
3438 		dlsp = (dl_capability_sub_t *)&dlzp[1];
3439 	}
3440 
3441 	if (macinfo->gldm_options & GLDOPT_MDT) {
3442 		dl_capab_mdt_t *dlmp = (dl_capab_mdt_t *)&dlsp[1];
3443 
3444 		dlsp->dl_cap = DL_CAPAB_MDT;
3445 		dlsp->dl_length = sizeof (dl_capab_mdt_t);
3446 
3447 		dlmp->mdt_version = MDT_VERSION_2;
3448 		dlmp->mdt_max_pld = macinfo->gldm_mdt_segs;
3449 		dlmp->mdt_span_limit = macinfo->gldm_mdt_sgl;
3450 		dlcapabsetqid(&dlmp->mdt_mid, OTHERQ(q));
3451 		dlmp->mdt_flags = DL_CAPAB_MDT_ENABLE;
3452 		dlmp->mdt_hdr_head = ifp->hdr_size;
3453 		dlmp->mdt_hdr_tail = 0;
3454 	}
3455 
3456 	qreply(q, mp);
3457 	return (GLDE_OK);
3458 }
3459 
3460 static int
3461 gld_cap_enable(queue_t *q, mblk_t *mp)
3462 {
3463 	dl_capability_req_t *dlp;
3464 	dl_capability_sub_t *dlsp;
3465 	dl_capab_hcksum_t *dlhp;
3466 	offset_t off;
3467 	size_t len;
3468 	size_t size;
3469 	offset_t end;
3470 
3471 	dlp = (dl_capability_req_t *)mp->b_rptr;
3472 	dlp->dl_primitive = DL_CAPABILITY_ACK;
3473 
3474 	off = dlp->dl_sub_offset;
3475 	len = dlp->dl_sub_length;
3476 
3477 	if (!MBLKIN(mp, off, len))
3478 		return (DL_BADPRIM);
3479 
3480 	end = off + len;
3481 	while (off < end) {
3482 		dlsp = (dl_capability_sub_t *)(mp->b_rptr + off);
3483 		size = sizeof (dl_capability_sub_t) + dlsp->dl_length;
3484 		if (off + size > end)
3485 			return (DL_BADPRIM);
3486 
3487 		switch (dlsp->dl_cap) {
3488 		case DL_CAPAB_HCKSUM:
3489 			dlhp = (dl_capab_hcksum_t *)&dlsp[1];
3490 			/* nothing useful we can do with the contents */
3491 			dlcapabsetqid(&(dlhp->hcksum_mid), RD(q));
3492 			break;
3493 		default:
3494 			break;
3495 		}
3496 
3497 		off += size;
3498 	}
3499 
3500 	qreply(q, mp);
3501 	return (GLDE_OK);
3502 }
3503 
3504 /*
3505  * Send a copy of the DL_NOTIFY_IND message <mp> to each stream that has
3506  * requested the specific <notification> that the message carries AND is
3507  * eligible and ready to receive the notification immediately.
3508  *
3509  * This routine ignores flow control. Notifications will be sent regardless.
3510  *
3511  * In all cases, the original message passed in is freed at the end of
3512  * the routine.
3513  */
3514 static void
3515 gld_notify_qs(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t notification)
3516 {
3517 	gld_mac_pvt_t *mac_pvt;
3518 	gld_vlan_t *vlan;
3519 	gld_t *gld;
3520 	mblk_t *nmp;
3521 	int i;
3522 
3523 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
3524 
3525 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3526 
3527 	/*
3528 	 * Search all the streams attached to this macinfo looking
3529 	 * for those eligible to receive the present notification.
3530 	 */
3531 	for (i = 0; i < VLAN_HASHSZ; i++) {
3532 		for (vlan = mac_pvt->vlan_hash[i];
3533 		    vlan != NULL; vlan = vlan->gldv_next) {
3534 			for (gld = vlan->gldv_str_next;
3535 			    gld != (gld_t *)&vlan->gldv_str_next;
3536 			    gld = gld->gld_next) {
3537 				ASSERT(gld->gld_qptr != NULL);
3538 				ASSERT(gld->gld_state == DL_IDLE ||
3539 				    gld->gld_state == DL_UNBOUND);
3540 				ASSERT(gld->gld_mac_info == macinfo);
3541 
3542 				if (gld->gld_flags & GLD_STR_CLOSING)
3543 					continue; /* not eligible - skip */
3544 				if (!(notification & gld->gld_notifications))
3545 					continue; /* not wanted - skip */
3546 				if ((nmp = dupmsg(mp)) == NULL)
3547 					continue; /* can't copy - skip */
3548 
3549 				/*
3550 				 * All OK; send dup'd notification up this
3551 				 * stream
3552 				 */
3553 				qreply(WR(gld->gld_qptr), nmp);
3554 			}
3555 		}
3556 	}
3557 
3558 	/*
3559 	 * Drop the original message block now
3560 	 */
3561 	freemsg(mp);
3562 }
3563 
3564 /*
3565  * For each (understood) bit in the <notifications> argument, contruct
3566  * a DL_NOTIFY_IND message and send it to the specified <q>, or to all
3567  * eligible queues if <q> is NULL.
3568  */
3569 static void
3570 gld_notify_ind(gld_mac_info_t *macinfo, uint32_t notifications, queue_t *q)
3571 {
3572 	gld_mac_pvt_t *mac_pvt;
3573 	dl_notify_ind_t *dlnip;
3574 	struct gld_stats *stats;
3575 	mblk_t *mp;
3576 	size_t size;
3577 	uint32_t bit;
3578 
3579 	GLDM_LOCK(macinfo, RW_WRITER);
3580 
3581 	/*
3582 	 * The following cases shouldn't happen, but just in case the
3583 	 * MAC driver calls gld_linkstate() at an inappropriate time, we
3584 	 * check anyway ...
3585 	 */
3586 	if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY)) {
3587 		GLDM_UNLOCK(macinfo);
3588 		return;				/* not ready yet	*/
3589 	}
3590 
3591 	if (macinfo->gldm_GLD_flags & GLD_UNREGISTERED) {
3592 		GLDM_UNLOCK(macinfo);
3593 		return;				/* not ready anymore	*/
3594 	}
3595 
3596 	/*
3597 	 * Make sure the kstats are up to date, 'cos we use some of
3598 	 * the kstat values below, specifically the link speed ...
3599 	 */
3600 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3601 	stats = mac_pvt->statistics;
3602 	if (macinfo->gldm_get_stats)
3603 		(void) (*macinfo->gldm_get_stats)(macinfo, stats);
3604 
3605 	for (bit = 1; notifications != 0; bit <<= 1) {
3606 		if ((notifications & bit) == 0)
3607 			continue;
3608 		notifications &= ~bit;
3609 
3610 		size = DL_NOTIFY_IND_SIZE;
3611 		if (bit == DL_NOTE_PHYS_ADDR)
3612 			size += macinfo->gldm_addrlen;
3613 		if ((mp = allocb(size, BPRI_MED)) == NULL)
3614 			continue;
3615 
3616 		mp->b_datap->db_type = M_PROTO;
3617 		mp->b_wptr = mp->b_rptr + size;
3618 		dlnip = (dl_notify_ind_t *)mp->b_rptr;
3619 		dlnip->dl_primitive = DL_NOTIFY_IND;
3620 		dlnip->dl_notification = 0;
3621 		dlnip->dl_data = 0;
3622 		dlnip->dl_addr_length = 0;
3623 		dlnip->dl_addr_offset = 0;
3624 
3625 		switch (bit) {
3626 		case DL_NOTE_PROMISC_ON_PHYS:
3627 		case DL_NOTE_PROMISC_OFF_PHYS:
3628 			if (mac_pvt->nprom != 0)
3629 				dlnip->dl_notification = bit;
3630 			break;
3631 
3632 		case DL_NOTE_LINK_DOWN:
3633 			if (macinfo->gldm_linkstate == GLD_LINKSTATE_DOWN)
3634 				dlnip->dl_notification = bit;
3635 			break;
3636 
3637 		case DL_NOTE_LINK_UP:
3638 			if (macinfo->gldm_linkstate == GLD_LINKSTATE_UP)
3639 				dlnip->dl_notification = bit;
3640 			break;
3641 
3642 		case DL_NOTE_SPEED:
3643 			/*
3644 			 * Conversion required here:
3645 			 *	GLD keeps the speed in bit/s in a uint64
3646 			 *	DLPI wants it in kb/s in a uint32
3647 			 * Fortunately this is still big enough for 10Gb/s!
3648 			 */
3649 			dlnip->dl_notification = bit;
3650 			dlnip->dl_data = stats->glds_speed/1000ULL;
3651 			break;
3652 
3653 		case DL_NOTE_PHYS_ADDR:
3654 			dlnip->dl_notification = bit;
3655 			dlnip->dl_data = DL_CURR_PHYS_ADDR;
3656 			dlnip->dl_addr_offset = sizeof (dl_notify_ind_t);
3657 			dlnip->dl_addr_length = macinfo->gldm_addrlen +
3658 			    abs(macinfo->gldm_saplen);
3659 			mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3660 			mac_copy(mac_pvt->curr_macaddr,
3661 			    mp->b_rptr + sizeof (dl_notify_ind_t),
3662 			    macinfo->gldm_addrlen);
3663 			break;
3664 
3665 		default:
3666 			break;
3667 		}
3668 
3669 		if (dlnip->dl_notification == 0)
3670 			freemsg(mp);
3671 		else if (q != NULL)
3672 			qreply(q, mp);
3673 		else
3674 			gld_notify_qs(macinfo, mp, bit);
3675 	}
3676 
3677 	GLDM_UNLOCK(macinfo);
3678 }
3679 
3680 /*
3681  * gld_notify_req - handle a DL_NOTIFY_REQ message
3682  */
3683 static int
3684 gld_notify_req(queue_t *q, mblk_t *mp)
3685 {
3686 	gld_t *gld = (gld_t *)q->q_ptr;
3687 	gld_mac_info_t *macinfo;
3688 	gld_mac_pvt_t *pvt;
3689 	dl_notify_req_t *dlnrp;
3690 	dl_notify_ack_t *dlnap;
3691 
3692 	ASSERT(gld != NULL);
3693 	ASSERT(gld->gld_qptr == RD(q));
3694 
3695 	dlnrp = (dl_notify_req_t *)mp->b_rptr;
3696 
3697 #ifdef GLD_DEBUG
3698 	if (gld_debug & GLDTRACE)
3699 		cmn_err(CE_NOTE, "gld_notify_req(%p %p)",
3700 			(void *)q, (void *)mp);
3701 #endif
3702 
3703 	if (gld->gld_state == DL_UNATTACHED) {
3704 #ifdef GLD_DEBUG
3705 		if (gld_debug & GLDERRS)
3706 			cmn_err(CE_NOTE, "gld_notify_req: wrong state (%d)",
3707 				gld->gld_state);
3708 #endif
3709 		return (DL_OUTSTATE);
3710 	}
3711 
3712 	/*
3713 	 * Remember what notifications are required by this stream
3714 	 */
3715 	macinfo = gld->gld_mac_info;
3716 	pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3717 
3718 	gld->gld_notifications = dlnrp->dl_notifications & pvt->notifications;
3719 
3720 	/*
3721 	 * The return DL_NOTIFY_ACK carries the bitset of notifications
3722 	 * that this driver can provide, independently of which ones have
3723 	 * previously been or are now being requested.
3724 	 */
3725 	if ((mp = mexchange(q, mp, sizeof (dl_notify_ack_t), M_PCPROTO,
3726 	    DL_NOTIFY_ACK)) == NULL)
3727 		return (DL_SYSERR);
3728 
3729 	dlnap = (dl_notify_ack_t *)mp->b_rptr;
3730 	dlnap->dl_notifications = pvt->notifications;
3731 	qreply(q, mp);
3732 
3733 	/*
3734 	 * A side effect of a DL_NOTIFY_REQ is that after the DL_NOTIFY_ACK
3735 	 * reply, the the requestor gets zero or more DL_NOTIFY_IND messages
3736 	 * that provide the current status.
3737 	 */
3738 	gld_notify_ind(macinfo, gld->gld_notifications, q);
3739 
3740 	return (GLDE_OK);
3741 }
3742 
3743 /*
3744  * gld_linkstate()
3745  *	Called by driver to tell GLD the state of the physical link.
3746  *	As a side effect, sends a DL_NOTE_LINK_UP or DL_NOTE_LINK_DOWN
3747  *	notification to each client that has previously requested such
3748  *	notifications
3749  */
3750 void
3751 gld_linkstate(gld_mac_info_t *macinfo, int32_t newstate)
3752 {
3753 	uint32_t notification;
3754 
3755 	switch (newstate) {
3756 	default:
3757 		return;
3758 
3759 	case GLD_LINKSTATE_DOWN:
3760 		notification = DL_NOTE_LINK_DOWN;
3761 		break;
3762 
3763 	case GLD_LINKSTATE_UP:
3764 		notification = DL_NOTE_LINK_UP | DL_NOTE_SPEED;
3765 		break;
3766 
3767 	case GLD_LINKSTATE_UNKNOWN:
3768 		notification = 0;
3769 		break;
3770 	}
3771 
3772 	GLDM_LOCK(macinfo, RW_WRITER);
3773 	if (macinfo->gldm_linkstate == newstate)
3774 		notification = 0;
3775 	else
3776 		macinfo->gldm_linkstate = newstate;
3777 	GLDM_UNLOCK(macinfo);
3778 
3779 	if (notification)
3780 		gld_notify_ind(macinfo, notification, NULL);
3781 }
3782 
3783 /*
3784  * gld_udqos - set the current QoS parameters (priority only at the moment).
3785  */
3786 static int
3787 gld_udqos(queue_t *q, mblk_t *mp)
3788 {
3789 	dl_udqos_req_t *dlp;
3790 	gld_t  *gld = (gld_t *)q->q_ptr;
3791 	int off;
3792 	int len;
3793 	dl_qos_cl_sel1_t *selp;
3794 
3795 	ASSERT(gld);
3796 	ASSERT(gld->gld_qptr == RD(q));
3797 
3798 #ifdef GLD_DEBUG
3799 	if (gld_debug & GLDTRACE)
3800 		cmn_err(CE_NOTE, "gld_udqos(%p %p)", (void *)q, (void *)mp);
3801 #endif
3802 
3803 	if (gld->gld_state != DL_IDLE) {
3804 #ifdef GLD_DEBUG
3805 		if (gld_debug & GLDERRS)
3806 			cmn_err(CE_NOTE, "gld_udqos: wrong state (%d)",
3807 			    gld->gld_state);
3808 #endif
3809 		return (DL_OUTSTATE);
3810 	}
3811 
3812 	dlp = (dl_udqos_req_t *)mp->b_rptr;
3813 	off = dlp->dl_qos_offset;
3814 	len = dlp->dl_qos_length;
3815 
3816 	if (len != sizeof (dl_qos_cl_sel1_t) || !MBLKIN(mp, off, len))
3817 		return (DL_BADQOSTYPE);
3818 
3819 	selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off);
3820 	if (selp->dl_qos_type != DL_QOS_CL_SEL1)
3821 		return (DL_BADQOSTYPE);
3822 
3823 	if (selp->dl_trans_delay != 0 &&
3824 	    selp->dl_trans_delay != DL_QOS_DONT_CARE)
3825 		return (DL_BADQOSPARAM);
3826 	if (selp->dl_protection != 0 &&
3827 	    selp->dl_protection != DL_QOS_DONT_CARE)
3828 		return (DL_BADQOSPARAM);
3829 	if (selp->dl_residual_error != 0 &&
3830 	    selp->dl_residual_error != DL_QOS_DONT_CARE)
3831 		return (DL_BADQOSPARAM);
3832 	if (selp->dl_priority < 0 || selp->dl_priority > 7)
3833 		return (DL_BADQOSPARAM);
3834 
3835 	gld->gld_upri = selp->dl_priority;
3836 
3837 	dlokack(q, mp, DL_UDQOS_REQ);
3838 	return (GLDE_OK);
3839 }
3840 
3841 static mblk_t *
3842 gld_bindack(queue_t *q, mblk_t *mp)
3843 {
3844 	gld_t *gld = (gld_t *)q->q_ptr;
3845 	gld_mac_info_t *macinfo = gld->gld_mac_info;
3846 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
3847 	dl_bind_ack_t *dlp;
3848 	size_t size;
3849 	t_uscalar_t addrlen;
3850 	uchar_t *sapp;
3851 
3852 	addrlen = macinfo->gldm_addrlen + abs(macinfo->gldm_saplen);
3853 	size = sizeof (dl_bind_ack_t) + addrlen;
3854 	if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL)
3855 		return (NULL);
3856 
3857 	dlp = (dl_bind_ack_t *)mp->b_rptr;
3858 	dlp->dl_sap = gld->gld_sap;
3859 	dlp->dl_addr_length = addrlen;
3860 	dlp->dl_addr_offset = sizeof (dl_bind_ack_t);
3861 	dlp->dl_max_conind = 0;
3862 	dlp->dl_xidtest_flg = 0;
3863 
3864 	mac_copy(mac_pvt->curr_macaddr, (uchar_t *)&dlp[1],
3865 	    macinfo->gldm_addrlen);
3866 	sapp = mp->b_rptr + dlp->dl_addr_offset + macinfo->gldm_addrlen;
3867 	*(ushort_t *)sapp = gld->gld_sap;
3868 
3869 	return (mp);
3870 }
3871 
3872 /*
3873  * gld_bind - determine if a SAP is already allocated and whether it is legal
3874  * to do the bind at this time
3875  */
3876 static int
3877 gld_bind(queue_t *q, mblk_t *mp)
3878 {
3879 	ulong_t	sap;
3880 	dl_bind_req_t *dlp;
3881 	gld_t *gld = (gld_t *)q->q_ptr;
3882 	gld_mac_info_t *macinfo = gld->gld_mac_info;
3883 
3884 	ASSERT(gld);
3885 	ASSERT(gld->gld_qptr == RD(q));
3886 
3887 #ifdef GLD_DEBUG
3888 	if (gld_debug & GLDTRACE)
3889 		cmn_err(CE_NOTE, "gld_bind(%p %p)", (void *)q, (void *)mp);
3890 #endif
3891 
3892 	dlp = (dl_bind_req_t *)mp->b_rptr;
3893 	sap = dlp->dl_sap;
3894 
3895 #ifdef GLD_DEBUG
3896 	if (gld_debug & GLDPROT)
3897 		cmn_err(CE_NOTE, "gld_bind: lsap=%lx", sap);
3898 #endif
3899 
3900 	if (gld->gld_state != DL_UNBOUND) {
3901 #ifdef GLD_DEBUG
3902 		if (gld_debug & GLDERRS)
3903 			cmn_err(CE_NOTE, "gld_bind: bound or not attached (%d)",
3904 				gld->gld_state);
3905 #endif
3906 		return (DL_OUTSTATE);
3907 	}
3908 	ASSERT(macinfo);
3909 
3910 	if (dlp->dl_service_mode != DL_CLDLS) {
3911 		return (DL_UNSUPPORTED);
3912 	}
3913 	if (dlp->dl_xidtest_flg & (DL_AUTO_XID | DL_AUTO_TEST)) {
3914 		return (DL_NOAUTO);
3915 	}
3916 
3917 	/*
3918 	 * Check sap validity and decide whether this stream accepts
3919 	 * IEEE 802.2 (LLC) packets.
3920 	 */
3921 	if (sap > ETHERTYPE_MAX)
3922 		return (DL_BADSAP);
3923 
3924 	/*
3925 	 * Decide whether the SAP value selects EtherType encoding/decoding.
3926 	 * For compatibility with monolithic ethernet drivers, the range of
3927 	 * SAP values is different for DL_ETHER media.
3928 	 */
3929 	switch (macinfo->gldm_type) {
3930 	case DL_ETHER:
3931 		gld->gld_ethertype = (sap > ETHERMTU);
3932 		break;
3933 	default:
3934 		gld->gld_ethertype = (sap > GLD_MAX_802_SAP);
3935 		break;
3936 	}
3937 
3938 	/* if we get to here, then the SAP is legal enough */
3939 	GLDM_LOCK(macinfo, RW_WRITER);
3940 	gld->gld_state = DL_IDLE;	/* bound and ready */
3941 	gld->gld_sap = sap;
3942 	gld_set_ipq(gld);
3943 
3944 #ifdef GLD_DEBUG
3945 	if (gld_debug & GLDPROT)
3946 		cmn_err(CE_NOTE, "gld_bind: ok - sap = %d", gld->gld_sap);
3947 #endif
3948 
3949 	/* ACK the BIND */
3950 	mp = gld_bindack(q, mp);
3951 	GLDM_UNLOCK(macinfo);
3952 
3953 	if (mp != NULL) {
3954 		qreply(q, mp);
3955 		return (GLDE_OK);
3956 	}
3957 
3958 	return (DL_SYSERR);
3959 }
3960 
3961 /*
3962  * gld_unbind - perform an unbind of an LSAP or ether type on the stream.
3963  * The stream is still open and can be re-bound.
3964  */
3965 static int
3966 gld_unbind(queue_t *q, mblk_t *mp)
3967 {
3968 	gld_t *gld = (gld_t *)q->q_ptr;
3969 	gld_mac_info_t *macinfo = gld->gld_mac_info;
3970 
3971 	ASSERT(gld);
3972 
3973 #ifdef GLD_DEBUG
3974 	if (gld_debug & GLDTRACE)
3975 		cmn_err(CE_NOTE, "gld_unbind(%p %p)", (void *)q, (void *)mp);
3976 #endif
3977 
3978 	if (gld->gld_state != DL_IDLE) {
3979 #ifdef GLD_DEBUG
3980 		if (gld_debug & GLDERRS)
3981 			cmn_err(CE_NOTE, "gld_unbind: wrong state (%d)",
3982 				gld->gld_state);
3983 #endif
3984 		return (DL_OUTSTATE);
3985 	}
3986 	ASSERT(macinfo);
3987 
3988 	/*
3989 	 * Avoid unbinding (DL_UNBIND_REQ) while FAST/RAW is inside wput.
3990 	 * See comments above gld_start().
3991 	 */
3992 	gld->gld_in_unbind = B_TRUE;	/* disallow wput=>start */
3993 	membar_enter();
3994 	if (gld->gld_wput_count != 0) {
3995 		gld->gld_in_unbind = B_FALSE;
3996 		ASSERT(mp);		/* we didn't come from close */
3997 #ifdef GLD_DEBUG
3998 		if (gld_debug & GLDETRACE)
3999 			cmn_err(CE_NOTE, "gld_unbind: defer for wput");
4000 #endif
4001 		(void) putbq(q, mp);
4002 		qenable(q);		/* try again soon */
4003 		return (GLDE_RETRY);
4004 	}
4005 
4006 	GLDM_LOCK(macinfo, RW_WRITER);
4007 	gld->gld_state = DL_UNBOUND;
4008 	gld->gld_sap = 0;
4009 	gld_set_ipq(gld);
4010 	GLDM_UNLOCK(macinfo);
4011 
4012 	membar_exit();
4013 	gld->gld_in_unbind = B_FALSE;
4014 
4015 	/* mp is NULL if we came from close */
4016 	if (mp) {
4017 		gld_flushqueue(q);	/* flush the queues */
4018 		dlokack(q, mp, DL_UNBIND_REQ);
4019 	}
4020 	return (GLDE_OK);
4021 }
4022 
4023 /*
4024  * gld_inforeq - generate the response to an info request
4025  */
4026 static int
4027 gld_inforeq(queue_t *q, mblk_t *mp)
4028 {
4029 	gld_t		*gld;
4030 	dl_info_ack_t	*dlp;
4031 	int		bufsize;
4032 	glddev_t	*glddev;
4033 	gld_mac_info_t	*macinfo;
4034 	gld_mac_pvt_t	*mac_pvt;
4035 	int		sel_offset = 0;
4036 	int		range_offset = 0;
4037 	int		addr_offset;
4038 	int		addr_length;
4039 	int		sap_length;
4040 	int		brdcst_offset;
4041 	int		brdcst_length;
4042 	gld_vlan_t	*vlan;
4043 	uchar_t		*sapp;
4044 
4045 #ifdef GLD_DEBUG
4046 	if (gld_debug & GLDTRACE)
4047 		cmn_err(CE_NOTE, "gld_inforeq(%p %p)", (void *)q, (void *)mp);
4048 #endif
4049 	gld = (gld_t *)q->q_ptr;
4050 	ASSERT(gld);
4051 	glddev = gld->gld_device;
4052 	ASSERT(glddev);
4053 
4054 	if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) {
4055 		macinfo = gld->gld_mac_info;
4056 		ASSERT(macinfo != NULL);
4057 
4058 		mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4059 
4060 		addr_length = macinfo->gldm_addrlen;
4061 		sap_length = macinfo->gldm_saplen;
4062 		brdcst_length = macinfo->gldm_addrlen;
4063 	} else {
4064 		addr_length = glddev->gld_addrlen;
4065 		sap_length = glddev->gld_saplen;
4066 		brdcst_length = glddev->gld_addrlen;
4067 	}
4068 
4069 	bufsize = sizeof (dl_info_ack_t);
4070 
4071 	addr_offset = bufsize;
4072 	bufsize += addr_length;
4073 	bufsize += abs(sap_length);
4074 
4075 	brdcst_offset = bufsize;
4076 	bufsize += brdcst_length;
4077 
4078 	if ((vlan = (gld_vlan_t *)gld->gld_vlan) != NULL &&
4079 	    vlan->gldv_id != VLAN_VID_NONE) {
4080 		sel_offset = P2ROUNDUP(bufsize, sizeof (int64_t));
4081 		bufsize = sel_offset + sizeof (dl_qos_cl_sel1_t);
4082 
4083 		range_offset = P2ROUNDUP(bufsize, sizeof (int64_t));
4084 		bufsize = range_offset + sizeof (dl_qos_cl_range1_t);
4085 	}
4086 
4087 	if ((mp = mexchange(q, mp, bufsize, M_PCPROTO, DL_INFO_ACK)) == NULL)
4088 		return (GLDE_OK);	/* nothing more to be done */
4089 
4090 	bzero(mp->b_rptr, bufsize);
4091 
4092 	dlp = (dl_info_ack_t *)mp->b_rptr;
4093 	dlp->dl_primitive = DL_INFO_ACK;
4094 	dlp->dl_version = DL_VERSION_2;
4095 	dlp->dl_service_mode = DL_CLDLS;
4096 	dlp->dl_current_state = gld->gld_state;
4097 	dlp->dl_provider_style = gld->gld_style;
4098 
4099 	if (sel_offset != 0) {
4100 		dl_qos_cl_sel1_t	*selp;
4101 		dl_qos_cl_range1_t	*rangep;
4102 
4103 		ASSERT(range_offset != 0);
4104 
4105 		dlp->dl_qos_offset = sel_offset;
4106 		dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
4107 		dlp->dl_qos_range_offset = range_offset;
4108 		dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
4109 
4110 		selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + sel_offset);
4111 		selp->dl_qos_type = DL_QOS_CL_SEL1;
4112 		selp->dl_priority = gld->gld_upri;
4113 
4114 		rangep = (dl_qos_cl_range1_t *)(mp->b_rptr + range_offset);
4115 		rangep->dl_qos_type = DL_QOS_CL_RANGE1;
4116 		rangep->dl_priority.dl_min = 0;
4117 		rangep->dl_priority.dl_max = 7;
4118 	}
4119 
4120 	if (gld->gld_state == DL_IDLE || gld->gld_state == DL_UNBOUND) {
4121 		dlp->dl_min_sdu = macinfo->gldm_minpkt;
4122 		dlp->dl_max_sdu = macinfo->gldm_maxpkt;
4123 		dlp->dl_mac_type = macinfo->gldm_type;
4124 		dlp->dl_addr_length = addr_length + abs(sap_length);
4125 		dlp->dl_sap_length = sap_length;
4126 
4127 		if (gld->gld_state == DL_IDLE) {
4128 			/*
4129 			 * If we are bound to a non-LLC SAP on any medium
4130 			 * other than Ethernet, then we need room for a
4131 			 * SNAP header.  So we have to adjust the MTU size
4132 			 * accordingly.  XXX I suppose this should be done
4133 			 * in gldutil.c, but it seems likely that this will
4134 			 * always be true for everything GLD supports but
4135 			 * Ethernet.  Check this if you add another medium.
4136 			 */
4137 			if ((macinfo->gldm_type == DL_TPR ||
4138 			    macinfo->gldm_type == DL_FDDI) &&
4139 			    gld->gld_ethertype)
4140 				dlp->dl_max_sdu -= LLC_SNAP_HDR_LEN;
4141 
4142 			/* copy macaddr and sap */
4143 			dlp->dl_addr_offset = addr_offset;
4144 
4145 			mac_copy(mac_pvt->curr_macaddr, mp->b_rptr +
4146 			    addr_offset, macinfo->gldm_addrlen);
4147 			sapp = mp->b_rptr + addr_offset +
4148 			    macinfo->gldm_addrlen;
4149 			*(ushort_t *)sapp = gld->gld_sap;
4150 		} else {
4151 			dlp->dl_addr_offset = 0;
4152 		}
4153 
4154 		/* copy broadcast addr */
4155 		dlp->dl_brdcst_addr_length = macinfo->gldm_addrlen;
4156 		dlp->dl_brdcst_addr_offset = brdcst_offset;
4157 		mac_copy((caddr_t)macinfo->gldm_broadcast_addr,
4158 		    mp->b_rptr + brdcst_offset, brdcst_length);
4159 	} else {
4160 		/*
4161 		 * No PPA is attached.
4162 		 * The best we can do is use the values provided
4163 		 * by the first mac that called gld_register.
4164 		 */
4165 		dlp->dl_min_sdu = glddev->gld_minsdu;
4166 		dlp->dl_max_sdu = glddev->gld_maxsdu;
4167 		dlp->dl_mac_type = glddev->gld_type;
4168 		dlp->dl_addr_length = addr_length + abs(sap_length);
4169 		dlp->dl_sap_length = sap_length;
4170 		dlp->dl_addr_offset = 0;
4171 		dlp->dl_brdcst_addr_offset = brdcst_offset;
4172 		dlp->dl_brdcst_addr_length = brdcst_length;
4173 		mac_copy((caddr_t)glddev->gld_broadcast,
4174 		    mp->b_rptr + brdcst_offset, brdcst_length);
4175 	}
4176 	qreply(q, mp);
4177 	return (GLDE_OK);
4178 }
4179 
4180 /*
4181  * gld_unitdata (q, mp)
4182  * send a datagram.  Destination address/lsap is in M_PROTO
4183  * message (first mblock), data is in remainder of message.
4184  *
4185  */
4186 static int
4187 gld_unitdata(queue_t *q, mblk_t *mp)
4188 {
4189 	gld_t *gld = (gld_t *)q->q_ptr;
4190 	dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr;
4191 	gld_mac_info_t *macinfo = gld->gld_mac_info;
4192 	size_t	msglen;
4193 	mblk_t	*nmp;
4194 	gld_interface_t *ifp;
4195 	uint32_t start;
4196 	uint32_t stuff;
4197 	uint32_t end;
4198 	uint32_t value;
4199 	uint32_t flags;
4200 	uint32_t upri;
4201 
4202 #ifdef GLD_DEBUG
4203 	if (gld_debug & GLDTRACE)
4204 		cmn_err(CE_NOTE, "gld_unitdata(%p %p)", (void *)q, (void *)mp);
4205 #endif
4206 
4207 	if (gld->gld_state != DL_IDLE) {
4208 #ifdef GLD_DEBUG
4209 		if (gld_debug & GLDERRS)
4210 			cmn_err(CE_NOTE, "gld_unitdata: wrong state (%d)",
4211 				gld->gld_state);
4212 #endif
4213 		dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4214 		    dlp->dl_dest_addr_length, DL_OUTSTATE, 0);
4215 		return (GLDE_OK);
4216 	}
4217 	ASSERT(macinfo != NULL);
4218 
4219 	if (!MBLKIN(mp, dlp->dl_dest_addr_offset, dlp->dl_dest_addr_length) ||
4220 	    dlp->dl_dest_addr_length !=
4221 	    macinfo->gldm_addrlen + abs(macinfo->gldm_saplen)) {
4222 		dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4223 		    dlp->dl_dest_addr_length, DL_BADADDR, 0);
4224 		return (GLDE_OK);
4225 	}
4226 
4227 	upri = dlp->dl_priority.dl_max;
4228 
4229 	msglen = msgdsize(mp);
4230 	if (msglen == 0 || msglen > macinfo->gldm_maxpkt) {
4231 #ifdef GLD_DEBUG
4232 		if (gld_debug & GLDERRS)
4233 			cmn_err(CE_NOTE, "gld_unitdata: bad msglen (%d)",
4234 				(int)msglen);
4235 #endif
4236 		dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4237 		    dlp->dl_dest_addr_length, DL_BADDATA, 0);
4238 		return (GLDE_OK);
4239 	}
4240 
4241 	ASSERT(mp->b_cont != NULL);	/* because msgdsize(mp) is nonzero */
4242 
4243 	ifp = ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->interfacep;
4244 
4245 	/* grab any checksum information that may be present */
4246 	hcksum_retrieve(mp->b_cont, NULL, NULL, &start, &stuff, &end,
4247 	    &value, &flags);
4248 
4249 	/*
4250 	 * Prepend a valid header for transmission
4251 	 */
4252 	if ((nmp = (*ifp->mkunitdata)(gld, mp)) == NULL) {
4253 #ifdef GLD_DEBUG
4254 		if (gld_debug & GLDERRS)
4255 			cmn_err(CE_NOTE, "gld_unitdata: mkunitdata failed.");
4256 #endif
4257 		dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
4258 		    dlp->dl_dest_addr_length, DL_SYSERR, ENOSR);
4259 		return (GLDE_OK);
4260 	}
4261 
4262 	/* apply any checksum information to the first block in the chain */
4263 	(void) hcksum_assoc(nmp, NULL, NULL, start, stuff, end, value,
4264 	    flags, 0);
4265 
4266 	if (gld_start(q, nmp, GLD_WSRV, upri) == GLD_NORESOURCES) {
4267 		qenable(q);
4268 		return (GLDE_RETRY);
4269 	}
4270 
4271 	return (GLDE_OK);
4272 }
4273 
4274 /*
4275  * gldattach(q, mp)
4276  * DLPI DL_ATTACH_REQ
4277  * this attaches the stream to a PPA
4278  */
4279 static int
4280 gldattach(queue_t *q, mblk_t *mp)
4281 {
4282 	dl_attach_req_t *at;
4283 	gld_mac_info_t *macinfo;
4284 	gld_t  *gld = (gld_t *)q->q_ptr;
4285 	glddev_t *glddev;
4286 	gld_mac_pvt_t *mac_pvt;
4287 	uint32_t ppa;
4288 	uint32_t vid;
4289 	gld_vlan_t *vlan;
4290 
4291 	at = (dl_attach_req_t *)mp->b_rptr;
4292 
4293 	if (gld->gld_state != DL_UNATTACHED)
4294 		return (DL_OUTSTATE);
4295 
4296 	ASSERT(!gld->gld_mac_info);
4297 
4298 	ppa = at->dl_ppa % GLD_VLAN_SCALE;	/* 0 .. 999	*/
4299 	vid = at->dl_ppa / GLD_VLAN_SCALE;	/* 0 .. 4094	*/
4300 	if (vid > VLAN_VID_MAX)
4301 		return (DL_BADPPA);
4302 
4303 	glddev = gld->gld_device;
4304 	mutex_enter(&glddev->gld_devlock);
4305 	for (macinfo = glddev->gld_mac_next;
4306 	    macinfo != (gld_mac_info_t *)&glddev->gld_mac_next;
4307 	    macinfo = macinfo->gldm_next) {
4308 		int inst;
4309 
4310 		ASSERT(macinfo != NULL);
4311 		if (macinfo->gldm_ppa != ppa)
4312 			continue;
4313 
4314 		if (!(macinfo->gldm_GLD_flags & GLD_MAC_READY))
4315 			continue;	/* this one's not ready yet */
4316 
4317 		/*
4318 		 * VLAN sanity check
4319 		 */
4320 		if (vid != VLAN_VID_NONE && !VLAN_CAPABLE(macinfo)) {
4321 			mutex_exit(&glddev->gld_devlock);
4322 			return (DL_BADPPA);
4323 		}
4324 
4325 		/*
4326 		 * We found the correct PPA, hold the instance
4327 		 */
4328 		inst = ddi_get_instance(macinfo->gldm_devinfo);
4329 		if (inst == -1 || qassociate(q, inst) != 0) {
4330 			mutex_exit(&glddev->gld_devlock);
4331 			return (DL_BADPPA);
4332 		}
4333 
4334 		/* Take the stream off the per-driver-class list */
4335 		gldremque(gld);
4336 
4337 		/*
4338 		 * We must hold the lock to prevent multiple calls
4339 		 * to the reset and start routines.
4340 		 */
4341 		GLDM_LOCK(macinfo, RW_WRITER);
4342 
4343 		gld->gld_mac_info = macinfo;
4344 
4345 		if (macinfo->gldm_send_tagged != NULL)
4346 			gld->gld_send = macinfo->gldm_send_tagged;
4347 		else
4348 			gld->gld_send = macinfo->gldm_send;
4349 
4350 		if ((vlan = gld_get_vlan(macinfo, vid)) == NULL) {
4351 			GLDM_UNLOCK(macinfo);
4352 			gldinsque(gld, glddev->gld_str_prev);
4353 			mutex_exit(&glddev->gld_devlock);
4354 			(void) qassociate(q, -1);
4355 			return (DL_BADPPA);
4356 		}
4357 
4358 		mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4359 		if (!mac_pvt->started) {
4360 			if (gld_start_mac(macinfo) != GLD_SUCCESS) {
4361 				gld_rem_vlan(vlan);
4362 				GLDM_UNLOCK(macinfo);
4363 				gldinsque(gld, glddev->gld_str_prev);
4364 				mutex_exit(&glddev->gld_devlock);
4365 				dlerrorack(q, mp, DL_ATTACH_REQ, DL_SYSERR,
4366 				    EIO);
4367 				(void) qassociate(q, -1);
4368 				return (GLDE_OK);
4369 			}
4370 		}
4371 
4372 		gld->gld_vlan = vlan;
4373 		vlan->gldv_nstreams++;
4374 		gldinsque(gld, vlan->gldv_str_prev);
4375 		gld->gld_state = DL_UNBOUND;
4376 		GLDM_UNLOCK(macinfo);
4377 
4378 #ifdef GLD_DEBUG
4379 		if (gld_debug & GLDPROT) {
4380 			cmn_err(CE_NOTE, "gldattach(%p, %p, PPA = %d)",
4381 			    (void *)q, (void *)mp, macinfo->gldm_ppa);
4382 		}
4383 #endif
4384 		mutex_exit(&glddev->gld_devlock);
4385 		dlokack(q, mp, DL_ATTACH_REQ);
4386 		return (GLDE_OK);
4387 	}
4388 	mutex_exit(&glddev->gld_devlock);
4389 	return (DL_BADPPA);
4390 }
4391 
4392 /*
4393  * gldunattach(q, mp)
4394  * DLPI DL_DETACH_REQ
4395  * detaches the mac layer from the stream
4396  */
4397 int
4398 gldunattach(queue_t *q, mblk_t *mp)
4399 {
4400 	gld_t  *gld = (gld_t *)q->q_ptr;
4401 	glddev_t *glddev = gld->gld_device;
4402 	gld_mac_info_t *macinfo = gld->gld_mac_info;
4403 	int	state = gld->gld_state;
4404 	int	i;
4405 	gld_mac_pvt_t *mac_pvt;
4406 	gld_vlan_t *vlan;
4407 	boolean_t phys_off;
4408 	boolean_t mult_off;
4409 	int op = GLD_MAC_PROMISC_NOOP;
4410 
4411 	if (state != DL_UNBOUND)
4412 		return (DL_OUTSTATE);
4413 
4414 	ASSERT(macinfo != NULL);
4415 	ASSERT(gld->gld_sap == 0);
4416 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4417 
4418 #ifdef GLD_DEBUG
4419 	if (gld_debug & GLDPROT) {
4420 		cmn_err(CE_NOTE, "gldunattach(%p, %p, PPA = %d)",
4421 		    (void *)q, (void *)mp, macinfo->gldm_ppa);
4422 	}
4423 #endif
4424 
4425 	GLDM_LOCK(macinfo, RW_WRITER);
4426 
4427 	if (gld->gld_mcast) {
4428 		for (i = 0; i < gld->gld_multicnt; i++) {
4429 			gld_mcast_t *mcast;
4430 
4431 			if ((mcast = gld->gld_mcast[i]) != NULL) {
4432 				ASSERT(mcast->gldm_refcnt);
4433 				gld_send_disable_multi(macinfo, mcast);
4434 			}
4435 		}
4436 		kmem_free(gld->gld_mcast,
4437 		    sizeof (gld_mcast_t *) * gld->gld_multicnt);
4438 		gld->gld_mcast = NULL;
4439 		gld->gld_multicnt = 0;
4440 	}
4441 
4442 	/* decide if we need to turn off any promiscuity */
4443 	phys_off = (gld->gld_flags & GLD_PROM_PHYS &&
4444 	    --mac_pvt->nprom == 0);
4445 	mult_off = (gld->gld_flags & GLD_PROM_MULT &&
4446 	    --mac_pvt->nprom_multi == 0);
4447 
4448 	gld->gld_flags &= ~(GLD_PROM_PHYS | GLD_PROM_SAP | GLD_PROM_MULT);
4449 
4450 	if (phys_off) {
4451 		op = (mac_pvt->nprom_multi == 0) ? GLD_MAC_PROMISC_NONE :
4452 		    GLD_MAC_PROMISC_MULTI;
4453 	} else if (mult_off) {
4454 		op = (mac_pvt->nprom == 0) ? GLD_MAC_PROMISC_NONE :
4455 		    GLD_MAC_PROMISC_NOOP;	/* phys overrides multi */
4456 	}
4457 
4458 	if (op != GLD_MAC_PROMISC_NOOP)
4459 		(void) (*macinfo->gldm_set_promiscuous)(macinfo, op);
4460 
4461 	GLDM_UNLOCK(macinfo);
4462 
4463 	if (phys_off)
4464 		gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL);
4465 
4466 	/*
4467 	 * We need to hold both locks when modifying the mac stream list
4468 	 * to protect findminor as well as everyone else.
4469 	 */
4470 	mutex_enter(&glddev->gld_devlock);
4471 	GLDM_LOCK(macinfo, RW_WRITER);
4472 
4473 	/* disassociate this stream with its vlan and underlying mac */
4474 	gldremque(gld);
4475 
4476 	vlan = (gld_vlan_t *)gld->gld_vlan;
4477 	if (--vlan->gldv_nstreams == 0) {
4478 		gld_rem_vlan(vlan);
4479 		gld->gld_vlan = NULL;
4480 	}
4481 
4482 	gld->gld_mac_info = NULL;
4483 	gld->gld_state = DL_UNATTACHED;
4484 
4485 	/* cleanup mac layer if last vlan */
4486 	if (mac_pvt->nvlan == 0) {
4487 		gld_stop_mac(macinfo);
4488 		macinfo->gldm_GLD_flags &= ~GLD_INTR_WAIT;
4489 	}
4490 
4491 	/* make sure no references to this gld for gld_v0_sched */
4492 	if (mac_pvt->last_sched == gld)
4493 		mac_pvt->last_sched = NULL;
4494 
4495 	GLDM_UNLOCK(macinfo);
4496 
4497 	/* put the stream on the unattached Style 2 list */
4498 	gldinsque(gld, glddev->gld_str_prev);
4499 
4500 	mutex_exit(&glddev->gld_devlock);
4501 
4502 	/* There will be no mp if we were called from close */
4503 	if (mp) {
4504 		dlokack(q, mp, DL_DETACH_REQ);
4505 	}
4506 	if (gld->gld_style == DL_STYLE2)
4507 		(void) qassociate(q, -1);
4508 	return (GLDE_OK);
4509 }
4510 
4511 /*
4512  * gld_enable_multi (q, mp)
4513  * Enables multicast address on the stream.  If the mac layer
4514  * isn't enabled for this address, enable at that level as well.
4515  */
4516 static int
4517 gld_enable_multi(queue_t *q, mblk_t *mp)
4518 {
4519 	gld_t  *gld = (gld_t *)q->q_ptr;
4520 	glddev_t *glddev;
4521 	gld_mac_info_t *macinfo = gld->gld_mac_info;
4522 	unsigned char *maddr;
4523 	dl_enabmulti_req_t *multi;
4524 	gld_mcast_t *mcast;
4525 	int	i, rc;
4526 	gld_mac_pvt_t *mac_pvt;
4527 
4528 #ifdef GLD_DEBUG
4529 	if (gld_debug & GLDPROT) {
4530 		cmn_err(CE_NOTE, "gld_enable_multi(%p, %p)", (void *)q,
4531 		    (void *)mp);
4532 	}
4533 #endif
4534 
4535 	if (gld->gld_state == DL_UNATTACHED)
4536 		return (DL_OUTSTATE);
4537 
4538 	ASSERT(macinfo != NULL);
4539 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4540 
4541 	if (macinfo->gldm_set_multicast == NULL) {
4542 		return (DL_UNSUPPORTED);
4543 	}
4544 
4545 	multi = (dl_enabmulti_req_t *)mp->b_rptr;
4546 
4547 	if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) ||
4548 	    multi->dl_addr_length != macinfo->gldm_addrlen)
4549 		return (DL_BADADDR);
4550 
4551 	/* request appears to be valid */
4552 
4553 	glddev = mac_pvt->major_dev;
4554 	ASSERT(glddev == gld->gld_device);
4555 
4556 	maddr = mp->b_rptr + multi->dl_addr_offset;
4557 
4558 	/*
4559 	 * The multicast addresses live in a per-device table, along
4560 	 * with a reference count.  Each stream has a table that
4561 	 * points to entries in the device table, with the reference
4562 	 * count reflecting the number of streams pointing at it.  If
4563 	 * this multicast address is already in the per-device table,
4564 	 * all we have to do is point at it.
4565 	 */
4566 	GLDM_LOCK(macinfo, RW_WRITER);
4567 
4568 	/* does this address appear in current table? */
4569 	if (gld->gld_mcast == NULL) {
4570 		/* no mcast addresses -- allocate table */
4571 		gld->gld_mcast = GETSTRUCT(gld_mcast_t *,
4572 					    glddev->gld_multisize);
4573 		if (gld->gld_mcast == NULL) {
4574 			GLDM_UNLOCK(macinfo);
4575 			dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
4576 			return (GLDE_OK);
4577 		}
4578 		gld->gld_multicnt = glddev->gld_multisize;
4579 	} else {
4580 		for (i = 0; i < gld->gld_multicnt; i++) {
4581 			if (gld->gld_mcast[i] &&
4582 			    mac_eq(gld->gld_mcast[i]->gldm_addr,
4583 				maddr, macinfo->gldm_addrlen)) {
4584 				/* this is a match -- just succeed */
4585 				ASSERT(gld->gld_mcast[i]->gldm_refcnt);
4586 				GLDM_UNLOCK(macinfo);
4587 				dlokack(q, mp, DL_ENABMULTI_REQ);
4588 				return (GLDE_OK);
4589 			}
4590 		}
4591 	}
4592 
4593 	/*
4594 	 * it wasn't in the stream so check to see if the mac layer has it
4595 	 */
4596 	mcast = NULL;
4597 	if (mac_pvt->mcast_table == NULL) {
4598 		mac_pvt->mcast_table = GETSTRUCT(gld_mcast_t,
4599 						glddev->gld_multisize);
4600 		if (mac_pvt->mcast_table == NULL) {
4601 			GLDM_UNLOCK(macinfo);
4602 			dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
4603 			return (GLDE_OK);
4604 		}
4605 	} else {
4606 		for (i = 0; i < glddev->gld_multisize; i++) {
4607 			if (mac_pvt->mcast_table[i].gldm_refcnt &&
4608 			    mac_eq(mac_pvt->mcast_table[i].gldm_addr,
4609 			    maddr, macinfo->gldm_addrlen)) {
4610 				mcast = &mac_pvt->mcast_table[i];
4611 				break;
4612 			}
4613 		}
4614 	}
4615 	if (mcast == NULL) {
4616 		/* not in mac layer -- find an empty mac slot to fill in */
4617 		for (i = 0; i < glddev->gld_multisize; i++) {
4618 			if (mac_pvt->mcast_table[i].gldm_refcnt == 0) {
4619 				mcast = &mac_pvt->mcast_table[i];
4620 				mac_copy(maddr, mcast->gldm_addr,
4621 				    macinfo->gldm_addrlen);
4622 				break;
4623 			}
4624 		}
4625 	}
4626 	if (mcast == NULL) {
4627 		/* couldn't get a mac layer slot */
4628 		GLDM_UNLOCK(macinfo);
4629 		return (DL_TOOMANY);
4630 	}
4631 
4632 	/* now we have a mac layer slot in mcast -- get a stream slot */
4633 	for (i = 0; i < gld->gld_multicnt; i++) {
4634 		if (gld->gld_mcast[i] != NULL)
4635 			continue;
4636 		/* found an empty slot */
4637 		if (!mcast->gldm_refcnt) {
4638 			/* set mcast in hardware */
4639 			unsigned char cmaddr[GLD_MAX_ADDRLEN];
4640 
4641 			ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
4642 			cmac_copy(maddr, cmaddr,
4643 			    macinfo->gldm_addrlen, macinfo);
4644 
4645 			rc = (*macinfo->gldm_set_multicast)
4646 			    (macinfo, cmaddr, GLD_MULTI_ENABLE);
4647 			if (rc == GLD_NOTSUPPORTED) {
4648 				GLDM_UNLOCK(macinfo);
4649 				return (DL_NOTSUPPORTED);
4650 			} else if (rc == GLD_NORESOURCES) {
4651 				GLDM_UNLOCK(macinfo);
4652 				return (DL_TOOMANY);
4653 			} else if (rc == GLD_BADARG) {
4654 				GLDM_UNLOCK(macinfo);
4655 				return (DL_BADADDR);
4656 			} else if (rc == GLD_RETRY) {
4657 				/*
4658 				 * The putbq and gld_xwait must be
4659 				 * within the lock to prevent races
4660 				 * with gld_sched.
4661 				 */
4662 				(void) putbq(q, mp);
4663 				gld->gld_xwait = B_TRUE;
4664 				GLDM_UNLOCK(macinfo);
4665 				return (GLDE_RETRY);
4666 			} else if (rc != GLD_SUCCESS) {
4667 				GLDM_UNLOCK(macinfo);
4668 				dlerrorack(q, mp, DL_ENABMULTI_REQ,
4669 				    DL_SYSERR, EIO);
4670 				return (GLDE_OK);
4671 			}
4672 		}
4673 		gld->gld_mcast[i] = mcast;
4674 		mcast->gldm_refcnt++;
4675 		GLDM_UNLOCK(macinfo);
4676 		dlokack(q, mp, DL_ENABMULTI_REQ);
4677 		return (GLDE_OK);
4678 	}
4679 
4680 	/* couldn't get a stream slot */
4681 	GLDM_UNLOCK(macinfo);
4682 	return (DL_TOOMANY);
4683 }
4684 
4685 
4686 /*
4687  * gld_disable_multi (q, mp)
4688  * Disable the multicast address on the stream.  If last
4689  * reference for the mac layer, disable there as well.
4690  */
4691 static int
4692 gld_disable_multi(queue_t *q, mblk_t *mp)
4693 {
4694 	gld_t  *gld;
4695 	gld_mac_info_t *macinfo;
4696 	unsigned char *maddr;
4697 	dl_disabmulti_req_t *multi;
4698 	int i;
4699 	gld_mcast_t *mcast;
4700 
4701 #ifdef GLD_DEBUG
4702 	if (gld_debug & GLDPROT) {
4703 		cmn_err(CE_NOTE, "gld_disable_multi(%p, %p)", (void *)q,
4704 		    (void *)mp);
4705 	}
4706 #endif
4707 
4708 	gld = (gld_t *)q->q_ptr;
4709 	if (gld->gld_state == DL_UNATTACHED)
4710 		return (DL_OUTSTATE);
4711 
4712 	macinfo = gld->gld_mac_info;
4713 	ASSERT(macinfo != NULL);
4714 	if (macinfo->gldm_set_multicast == NULL) {
4715 		return (DL_UNSUPPORTED);
4716 	}
4717 
4718 	multi = (dl_disabmulti_req_t *)mp->b_rptr;
4719 
4720 	if (!MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) ||
4721 	    multi->dl_addr_length != macinfo->gldm_addrlen)
4722 		return (DL_BADADDR);
4723 
4724 	maddr = mp->b_rptr + multi->dl_addr_offset;
4725 
4726 	/* request appears to be valid */
4727 	/* does this address appear in current table? */
4728 	GLDM_LOCK(macinfo, RW_WRITER);
4729 	if (gld->gld_mcast != NULL) {
4730 		for (i = 0; i < gld->gld_multicnt; i++)
4731 			if (((mcast = gld->gld_mcast[i]) != NULL) &&
4732 			    mac_eq(mcast->gldm_addr,
4733 			    maddr, macinfo->gldm_addrlen)) {
4734 				ASSERT(mcast->gldm_refcnt);
4735 				gld_send_disable_multi(macinfo, mcast);
4736 				gld->gld_mcast[i] = NULL;
4737 				GLDM_UNLOCK(macinfo);
4738 				dlokack(q, mp, DL_DISABMULTI_REQ);
4739 				return (GLDE_OK);
4740 			}
4741 	}
4742 	GLDM_UNLOCK(macinfo);
4743 	return (DL_NOTENAB); /* not an enabled address */
4744 }
4745 
4746 /*
4747  * gld_send_disable_multi(macinfo, mcast)
4748  * this function is used to disable a multicast address if the reference
4749  * count goes to zero. The disable request will then be forwarded to the
4750  * lower stream.
4751  */
4752 static void
4753 gld_send_disable_multi(gld_mac_info_t *macinfo, gld_mcast_t *mcast)
4754 {
4755 	ASSERT(macinfo != NULL);
4756 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
4757 	ASSERT(mcast != NULL);
4758 	ASSERT(mcast->gldm_refcnt);
4759 
4760 	if (!mcast->gldm_refcnt) {
4761 		return;			/* "cannot happen" */
4762 	}
4763 
4764 	if (--mcast->gldm_refcnt > 0) {
4765 		return;
4766 	}
4767 
4768 	/*
4769 	 * This must be converted from canonical form to device form.
4770 	 * The refcnt is now zero so we can trash the data.
4771 	 */
4772 	if (macinfo->gldm_options & GLDOPT_CANONICAL_ADDR)
4773 		gld_bitreverse(mcast->gldm_addr, macinfo->gldm_addrlen);
4774 
4775 	/* XXX Ought to check for GLD_NORESOURCES or GLD_FAILURE */
4776 	(void) (*macinfo->gldm_set_multicast)
4777 	    (macinfo, mcast->gldm_addr, GLD_MULTI_DISABLE);
4778 }
4779 
4780 /*
4781  * gld_promisc (q, mp, req, on)
4782  *	enable or disable the use of promiscuous mode with the hardware
4783  */
4784 static int
4785 gld_promisc(queue_t *q, mblk_t *mp, t_uscalar_t req, boolean_t on)
4786 {
4787 	gld_t *gld;
4788 	gld_mac_info_t *macinfo;
4789 	gld_mac_pvt_t *mac_pvt;
4790 	gld_vlan_t *vlan;
4791 	union DL_primitives *prim;
4792 	int macrc = GLD_SUCCESS;
4793 	int dlerr = GLDE_OK;
4794 	int op = GLD_MAC_PROMISC_NOOP;
4795 
4796 #ifdef GLD_DEBUG
4797 	if (gld_debug & GLDTRACE)
4798 		cmn_err(CE_NOTE, "gld_promisc(%p, %p, %d, %d)",
4799 		    (void *)q, (void *)mp, req, on);
4800 #endif
4801 
4802 	ASSERT(mp != NULL);
4803 	prim = (union DL_primitives *)mp->b_rptr;
4804 
4805 	/* XXX I think spec allows promisc in unattached state */
4806 	gld = (gld_t *)q->q_ptr;
4807 	if (gld->gld_state == DL_UNATTACHED)
4808 		return (DL_OUTSTATE);
4809 
4810 	macinfo = gld->gld_mac_info;
4811 	ASSERT(macinfo != NULL);
4812 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
4813 
4814 	vlan = (gld_vlan_t *)gld->gld_vlan;
4815 	ASSERT(vlan != NULL);
4816 
4817 	GLDM_LOCK(macinfo, RW_WRITER);
4818 
4819 	/*
4820 	 * Work out what request (if any) has to be made to the MAC layer
4821 	 */
4822 	if (on) {
4823 		switch (prim->promiscon_req.dl_level) {
4824 		default:
4825 			dlerr = DL_UNSUPPORTED;	/* this is an error */
4826 			break;
4827 
4828 		case DL_PROMISC_PHYS:
4829 			if (mac_pvt->nprom == 0)
4830 				op = GLD_MAC_PROMISC_PHYS;
4831 			break;
4832 
4833 		case DL_PROMISC_MULTI:
4834 			if (mac_pvt->nprom_multi == 0)
4835 				if (mac_pvt->nprom == 0)
4836 					op = GLD_MAC_PROMISC_MULTI;
4837 			break;
4838 
4839 		case DL_PROMISC_SAP:
4840 			/* We can do this without reference to the MAC */
4841 			break;
4842 		}
4843 	} else {
4844 		switch (prim->promiscoff_req.dl_level) {
4845 		default:
4846 			dlerr = DL_UNSUPPORTED;	/* this is an error */
4847 			break;
4848 
4849 		case DL_PROMISC_PHYS:
4850 			if (!(gld->gld_flags & GLD_PROM_PHYS))
4851 				dlerr = DL_NOTENAB;
4852 			else if (mac_pvt->nprom == 1)
4853 				if (mac_pvt->nprom_multi)
4854 					op = GLD_MAC_PROMISC_MULTI;
4855 				else
4856 					op = GLD_MAC_PROMISC_NONE;
4857 			break;
4858 
4859 		case DL_PROMISC_MULTI:
4860 			if (!(gld->gld_flags & GLD_PROM_MULT))
4861 				dlerr = DL_NOTENAB;
4862 			else if (mac_pvt->nprom_multi == 1)
4863 				if (mac_pvt->nprom == 0)
4864 					op = GLD_MAC_PROMISC_NONE;
4865 			break;
4866 
4867 		case DL_PROMISC_SAP:
4868 			if (!(gld->gld_flags & GLD_PROM_SAP))
4869 				dlerr = DL_NOTENAB;
4870 
4871 			/* We can do this without reference to the MAC */
4872 			break;
4873 		}
4874 	}
4875 
4876 	/*
4877 	 * The request was invalid in some way so no need to continue.
4878 	 */
4879 	if (dlerr != GLDE_OK) {
4880 		GLDM_UNLOCK(macinfo);
4881 		return (dlerr);
4882 	}
4883 
4884 	/*
4885 	 * Issue the request to the MAC layer, if required
4886 	 */
4887 	if (op != GLD_MAC_PROMISC_NOOP) {
4888 		macrc = (*macinfo->gldm_set_promiscuous)(macinfo, op);
4889 	}
4890 
4891 	/*
4892 	 * On success, update the appropriate flags & refcounts
4893 	 */
4894 	if (macrc == GLD_SUCCESS) {
4895 		if (on) {
4896 			switch (prim->promiscon_req.dl_level) {
4897 			case DL_PROMISC_PHYS:
4898 				mac_pvt->nprom++;
4899 				gld->gld_flags |= GLD_PROM_PHYS;
4900 				break;
4901 
4902 			case DL_PROMISC_MULTI:
4903 				mac_pvt->nprom_multi++;
4904 				gld->gld_flags |= GLD_PROM_MULT;
4905 				break;
4906 
4907 			case DL_PROMISC_SAP:
4908 				gld->gld_flags |= GLD_PROM_SAP;
4909 				break;
4910 
4911 			default:
4912 				break;
4913 			}
4914 		} else {
4915 			switch (prim->promiscoff_req.dl_level) {
4916 			case DL_PROMISC_PHYS:
4917 				mac_pvt->nprom--;
4918 				gld->gld_flags &= ~GLD_PROM_PHYS;
4919 				break;
4920 
4921 			case DL_PROMISC_MULTI:
4922 				mac_pvt->nprom_multi--;
4923 				gld->gld_flags &= ~GLD_PROM_MULT;
4924 				break;
4925 
4926 			case DL_PROMISC_SAP:
4927 				gld->gld_flags &= ~GLD_PROM_SAP;
4928 				break;
4929 
4930 			default:
4931 				break;
4932 			}
4933 		}
4934 	} else if (macrc == GLD_RETRY) {
4935 		/*
4936 		 * The putbq and gld_xwait must be within the lock to
4937 		 * prevent races with gld_sched.
4938 		 */
4939 		(void) putbq(q, mp);
4940 		gld->gld_xwait = B_TRUE;
4941 	}
4942 
4943 	/*
4944 	 * Update VLAN IPQ status -- it may have changed
4945 	 */
4946 	if (gld->gld_flags & (GLD_PROM_SAP | GLD_PROM_MULT | GLD_PROM_PHYS))
4947 		vlan->gldv_ipq_flags |= IPQ_FORBIDDEN;
4948 	else
4949 		vlan->gldv_ipq_flags &= ~IPQ_FORBIDDEN;
4950 
4951 	GLDM_UNLOCK(macinfo);
4952 
4953 	/*
4954 	 * Finally, decide how to reply.
4955 	 *
4956 	 * If <macrc> is not GLD_SUCCESS, the request was put to the MAC
4957 	 * layer but failed.  In such cases, we can return a DL_* error
4958 	 * code and let the caller send an error-ack reply upstream, or
4959 	 * we can send a reply here and then return GLDE_OK so that the
4960 	 * caller doesn't also respond.
4961 	 *
4962 	 * If physical-promiscuous mode was (successfully) switched on or
4963 	 * off, send a notification (DL_NOTIFY_IND) to anyone interested.
4964 	 */
4965 	switch (macrc) {
4966 	case GLD_NOTSUPPORTED:
4967 		return (DL_NOTSUPPORTED);
4968 
4969 	case GLD_NORESOURCES:
4970 		dlerrorack(q, mp, req, DL_SYSERR, ENOSR);
4971 		return (GLDE_OK);
4972 
4973 	case GLD_RETRY:
4974 		return (GLDE_RETRY);
4975 
4976 	default:
4977 		dlerrorack(q, mp, req, DL_SYSERR, EIO);
4978 		return (GLDE_OK);
4979 
4980 	case GLD_SUCCESS:
4981 		dlokack(q, mp, req);
4982 		break;
4983 	}
4984 
4985 	switch (op) {
4986 	case GLD_MAC_PROMISC_NOOP:
4987 		break;
4988 
4989 	case GLD_MAC_PROMISC_PHYS:
4990 		gld_notify_ind(macinfo, DL_NOTE_PROMISC_ON_PHYS, NULL);
4991 		break;
4992 
4993 	default:
4994 		gld_notify_ind(macinfo, DL_NOTE_PROMISC_OFF_PHYS, NULL);
4995 		break;
4996 	}
4997 
4998 	return (GLDE_OK);
4999 }
5000 
5001 /*
5002  * gld_physaddr()
5003  *	get the current or factory physical address value
5004  */
5005 static int
5006 gld_physaddr(queue_t *q, mblk_t *mp)
5007 {
5008 	gld_t *gld = (gld_t *)q->q_ptr;
5009 	gld_mac_info_t *macinfo;
5010 	union DL_primitives *prim = (union DL_primitives *)mp->b_rptr;
5011 	unsigned char addr[GLD_MAX_ADDRLEN];
5012 
5013 	if (gld->gld_state == DL_UNATTACHED)
5014 		return (DL_OUTSTATE);
5015 
5016 	macinfo = (gld_mac_info_t *)gld->gld_mac_info;
5017 	ASSERT(macinfo != NULL);
5018 	ASSERT(macinfo->gldm_addrlen <= GLD_MAX_ADDRLEN);
5019 
5020 	switch (prim->physaddr_req.dl_addr_type) {
5021 	case DL_FACT_PHYS_ADDR:
5022 		mac_copy((caddr_t)macinfo->gldm_vendor_addr,
5023 		    (caddr_t)addr, macinfo->gldm_addrlen);
5024 		break;
5025 	case DL_CURR_PHYS_ADDR:
5026 		/* make a copy so we don't hold the lock across qreply */
5027 		GLDM_LOCK(macinfo, RW_WRITER);
5028 		mac_copy((caddr_t)
5029 		    ((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)->curr_macaddr,
5030 		    (caddr_t)addr, macinfo->gldm_addrlen);
5031 		GLDM_UNLOCK(macinfo);
5032 		break;
5033 	default:
5034 		return (DL_BADPRIM);
5035 	}
5036 	dlphysaddrack(q, mp, (caddr_t)addr, macinfo->gldm_addrlen);
5037 	return (GLDE_OK);
5038 }
5039 
5040 /*
5041  * gld_setaddr()
5042  *	change the hardware's physical address to a user specified value
5043  */
5044 static int
5045 gld_setaddr(queue_t *q, mblk_t *mp)
5046 {
5047 	gld_t *gld = (gld_t *)q->q_ptr;
5048 	gld_mac_info_t *macinfo;
5049 	gld_mac_pvt_t *mac_pvt;
5050 	union DL_primitives *prim = (union DL_primitives *)mp->b_rptr;
5051 	unsigned char *addr;
5052 	unsigned char cmaddr[GLD_MAX_ADDRLEN];
5053 	int rc;
5054 	gld_vlan_t *vlan;
5055 
5056 	if (gld->gld_state == DL_UNATTACHED)
5057 		return (DL_OUTSTATE);
5058 
5059 	vlan = (gld_vlan_t *)gld->gld_vlan;
5060 	ASSERT(vlan != NULL);
5061 
5062 	if (vlan->gldv_id != VLAN_VID_NONE)
5063 		return (DL_NOTSUPPORTED);
5064 
5065 	macinfo = (gld_mac_info_t *)gld->gld_mac_info;
5066 	ASSERT(macinfo != NULL);
5067 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5068 
5069 	if (!MBLKIN(mp, prim->set_physaddr_req.dl_addr_offset,
5070 	    prim->set_physaddr_req.dl_addr_length) ||
5071 	    prim->set_physaddr_req.dl_addr_length != macinfo->gldm_addrlen)
5072 		return (DL_BADADDR);
5073 
5074 	GLDM_LOCK(macinfo, RW_WRITER);
5075 
5076 	/* now do the set at the hardware level */
5077 	addr = mp->b_rptr + prim->set_physaddr_req.dl_addr_offset;
5078 	ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
5079 	cmac_copy(addr, cmaddr, macinfo->gldm_addrlen, macinfo);
5080 
5081 	rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr);
5082 	if (rc == GLD_SUCCESS)
5083 		mac_copy(addr, mac_pvt->curr_macaddr,
5084 		    macinfo->gldm_addrlen);
5085 
5086 	GLDM_UNLOCK(macinfo);
5087 
5088 	switch (rc) {
5089 	case GLD_SUCCESS:
5090 		break;
5091 	case GLD_NOTSUPPORTED:
5092 		return (DL_NOTSUPPORTED);
5093 	case GLD_BADARG:
5094 		return (DL_BADADDR);
5095 	case GLD_NORESOURCES:
5096 		dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOSR);
5097 		return (GLDE_OK);
5098 	default:
5099 		dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, EIO);
5100 		return (GLDE_OK);
5101 	}
5102 
5103 	gld_notify_ind(macinfo, DL_NOTE_PHYS_ADDR, NULL);
5104 
5105 	dlokack(q, mp, DL_SET_PHYS_ADDR_REQ);
5106 	return (GLDE_OK);
5107 }
5108 
5109 int
5110 gld_get_statistics(queue_t *q, mblk_t *mp)
5111 {
5112 	dl_get_statistics_ack_t *dlsp;
5113 	gld_t  *gld = (gld_t *)q->q_ptr;
5114 	gld_mac_info_t *macinfo = gld->gld_mac_info;
5115 	gld_mac_pvt_t *mac_pvt;
5116 
5117 	if (gld->gld_state == DL_UNATTACHED)
5118 		return (DL_OUTSTATE);
5119 
5120 	ASSERT(macinfo != NULL);
5121 
5122 	mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5123 	(void) gld_update_kstat(mac_pvt->kstatp, KSTAT_READ);
5124 
5125 	mp = mexchange(q, mp, DL_GET_STATISTICS_ACK_SIZE +
5126 	    sizeof (struct gldkstats), M_PCPROTO, DL_GET_STATISTICS_ACK);
5127 
5128 	if (mp == NULL)
5129 		return (GLDE_OK);	/* mexchange already sent merror */
5130 
5131 	dlsp = (dl_get_statistics_ack_t *)mp->b_rptr;
5132 	dlsp->dl_primitive = DL_GET_STATISTICS_ACK;
5133 	dlsp->dl_stat_length = sizeof (struct gldkstats);
5134 	dlsp->dl_stat_offset = DL_GET_STATISTICS_ACK_SIZE;
5135 
5136 	GLDM_LOCK(macinfo, RW_WRITER);
5137 	bcopy(mac_pvt->kstatp->ks_data,
5138 	    (mp->b_rptr + DL_GET_STATISTICS_ACK_SIZE),
5139 	    sizeof (struct gldkstats));
5140 	GLDM_UNLOCK(macinfo);
5141 
5142 	qreply(q, mp);
5143 	return (GLDE_OK);
5144 }
5145 
5146 /* =================================================== */
5147 /* misc utilities, some requiring various mutexes held */
5148 /* =================================================== */
5149 
5150 /*
5151  * Initialize and start the driver.
5152  */
5153 static int
5154 gld_start_mac(gld_mac_info_t *macinfo)
5155 {
5156 	int	rc;
5157 	unsigned char cmaddr[GLD_MAX_ADDRLEN];
5158 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5159 
5160 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5161 	ASSERT(!mac_pvt->started);
5162 
5163 	rc = (*macinfo->gldm_reset)(macinfo);
5164 	if (rc != GLD_SUCCESS)
5165 		return (GLD_FAILURE);
5166 
5167 	/* set the addr after we reset the device */
5168 	ASSERT(sizeof (cmaddr) >= macinfo->gldm_addrlen);
5169 	cmac_copy(((gld_mac_pvt_t *)macinfo->gldm_mac_pvt)
5170 	    ->curr_macaddr, cmaddr, macinfo->gldm_addrlen, macinfo);
5171 
5172 	rc = (*macinfo->gldm_set_mac_addr)(macinfo, cmaddr);
5173 	ASSERT(rc != GLD_BADARG);  /* this address was good before */
5174 	if (rc != GLD_SUCCESS && rc != GLD_NOTSUPPORTED)
5175 		return (GLD_FAILURE);
5176 
5177 	rc = (*macinfo->gldm_start)(macinfo);
5178 	if (rc != GLD_SUCCESS)
5179 		return (GLD_FAILURE);
5180 
5181 	mac_pvt->started = B_TRUE;
5182 	return (GLD_SUCCESS);
5183 }
5184 
5185 /*
5186  * Stop the driver.
5187  */
5188 static void
5189 gld_stop_mac(gld_mac_info_t *macinfo)
5190 {
5191 	gld_mac_pvt_t *mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5192 
5193 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5194 	ASSERT(mac_pvt->started);
5195 
5196 	(void) (*macinfo->gldm_stop)(macinfo);
5197 
5198 	mac_pvt->started = B_FALSE;
5199 }
5200 
5201 
5202 /*
5203  * gld_set_ipq will set a pointer to the queue which is bound to the
5204  * IP sap if:
5205  * o the device type is ethernet or IPoIB.
5206  * o there is no stream in SAP promiscuous mode.
5207  * o there is exactly one stream bound to the IP sap.
5208  * o the stream is in "fastpath" mode.
5209  */
5210 static void
5211 gld_set_ipq(gld_t *gld)
5212 {
5213 	gld_vlan_t	*vlan;
5214 	gld_mac_info_t	*macinfo = gld->gld_mac_info;
5215 	gld_t		*ip_gld = NULL;
5216 	uint_t		ipq_candidates = 0;
5217 	gld_t		*ipv6_gld = NULL;
5218 	uint_t		ipv6q_candidates = 0;
5219 
5220 	ASSERT(GLDM_LOCK_HELD_WRITE(macinfo));
5221 
5222 	/* The ipq code in gld_recv() is intimate with ethernet/IPoIB */
5223 	if (((macinfo->gldm_type != DL_ETHER) &&
5224 	    (macinfo->gldm_type != DL_IB)) ||
5225 	    (gld_global_options & GLD_OPT_NO_IPQ))
5226 		return;
5227 
5228 	vlan = (gld_vlan_t *)gld->gld_vlan;
5229 	ASSERT(vlan != NULL);
5230 
5231 	/* clear down any previously defined ipqs */
5232 	vlan->gldv_ipq = NULL;
5233 	vlan->gldv_ipv6q = NULL;
5234 
5235 	/* Try to find a single stream eligible to receive IP packets */
5236 	for (gld = vlan->gldv_str_next;
5237 	    gld != (gld_t *)&vlan->gldv_str_next; gld = gld->gld_next) {
5238 		if (gld->gld_state != DL_IDLE)
5239 			continue;	/* not eligible to receive */
5240 		if (gld->gld_flags & GLD_STR_CLOSING)
5241 			continue;	/* not eligible to receive */
5242 
5243 		if (gld->gld_sap == ETHERTYPE_IP) {
5244 			ip_gld = gld;
5245 			ipq_candidates++;
5246 		}
5247 
5248 		if (gld->gld_sap == ETHERTYPE_IPV6) {
5249 			ipv6_gld = gld;
5250 			ipv6q_candidates++;
5251 		}
5252 	}
5253 
5254 	if (ipq_candidates == 1) {
5255 		ASSERT(ip_gld != NULL);
5256 
5257 		if (ip_gld->gld_flags & GLD_FAST)	/* eligible for ipq */
5258 			vlan->gldv_ipq = ip_gld->gld_qptr;
5259 	}
5260 
5261 	if (ipv6q_candidates == 1) {
5262 		ASSERT(ipv6_gld != NULL);
5263 
5264 		if (ipv6_gld->gld_flags & GLD_FAST)	/* eligible for ipq */
5265 			vlan->gldv_ipv6q = ipv6_gld->gld_qptr;
5266 	}
5267 }
5268 
5269 /*
5270  * gld_flushqueue (q)
5271  *	used by DLPI primitives that require flushing the queues.
5272  *	essentially, this is DL_UNBIND_REQ.
5273  */
5274 static void
5275 gld_flushqueue(queue_t *q)
5276 {
5277 	/* flush all data in both queues */
5278 	/* XXX Should these be FLUSHALL? */
5279 	flushq(q, FLUSHDATA);
5280 	flushq(WR(q), FLUSHDATA);
5281 	/* flush all the queues upstream */
5282 	(void) putctl1(q, M_FLUSH, FLUSHRW);
5283 }
5284 
5285 /*
5286  * gld_devlookup (major)
5287  * search the device table for the device with specified
5288  * major number and return a pointer to it if it exists
5289  */
5290 static glddev_t *
5291 gld_devlookup(int major)
5292 {
5293 	struct glddevice *dev;
5294 
5295 	ASSERT(mutex_owned(&gld_device_list.gld_devlock));
5296 
5297 	for (dev = gld_device_list.gld_next;
5298 	    dev != &gld_device_list;
5299 	    dev = dev->gld_next) {
5300 		ASSERT(dev);
5301 		if (dev->gld_major == major)
5302 			return (dev);
5303 	}
5304 	return (NULL);
5305 }
5306 
5307 /*
5308  * gld_findminor(device)
5309  * Returns a minor number currently unused by any stream in the current
5310  * device class (major) list.
5311  */
5312 static int
5313 gld_findminor(glddev_t *device)
5314 {
5315 	gld_t		*next;
5316 	gld_mac_info_t	*nextmac;
5317 	gld_vlan_t	*nextvlan;
5318 	int		minor;
5319 	int		i;
5320 
5321 	ASSERT(mutex_owned(&device->gld_devlock));
5322 
5323 	/* The fast way */
5324 	if (device->gld_nextminor >= GLD_MIN_CLONE_MINOR &&
5325 	    device->gld_nextminor <= GLD_MAX_CLONE_MINOR)
5326 		return (device->gld_nextminor++);
5327 
5328 	/* The steady way */
5329 	for (minor = GLD_MIN_CLONE_MINOR; minor <= GLD_MAX_CLONE_MINOR;
5330 	    minor++) {
5331 		/* Search all unattached streams */
5332 		for (next = device->gld_str_next;
5333 		    next != (gld_t *)&device->gld_str_next;
5334 		    next = next->gld_next) {
5335 			if (minor == next->gld_minor)
5336 				goto nextminor;
5337 		}
5338 		/* Search all attached streams; we don't need maclock because */
5339 		/* mac stream list is protected by devlock as well as maclock */
5340 		for (nextmac = device->gld_mac_next;
5341 		    nextmac != (gld_mac_info_t *)&device->gld_mac_next;
5342 		    nextmac = nextmac->gldm_next) {
5343 			gld_mac_pvt_t *pvt =
5344 			    (gld_mac_pvt_t *)nextmac->gldm_mac_pvt;
5345 
5346 			if (!(nextmac->gldm_GLD_flags & GLD_MAC_READY))
5347 				continue;	/* this one's not ready yet */
5348 
5349 			for (i = 0; i < VLAN_HASHSZ; i++) {
5350 				for (nextvlan = pvt->vlan_hash[i];
5351 				    nextvlan != NULL;
5352 				    nextvlan = nextvlan->gldv_next) {
5353 					for (next = nextvlan->gldv_str_next;
5354 					    next !=
5355 					    (gld_t *)&nextvlan->gldv_str_next;
5356 					    next = next->gld_next) {
5357 						if (minor == next->gld_minor)
5358 							goto nextminor;
5359 					}
5360 				}
5361 			}
5362 		}
5363 
5364 		return (minor);
5365 nextminor:
5366 		/* don't need to do anything */
5367 		;
5368 	}
5369 	cmn_err(CE_WARN, "GLD ran out of minor numbers for %s",
5370 		device->gld_name);
5371 	return (0);
5372 }
5373 
5374 /*
5375  * version of insque/remque for use by this driver
5376  */
5377 struct qelem {
5378 	struct qelem *q_forw;
5379 	struct qelem *q_back;
5380 	/* rest of structure */
5381 };
5382 
5383 static void
5384 gldinsque(void *elem, void *pred)
5385 {
5386 	struct qelem *pelem = elem;
5387 	struct qelem *ppred = pred;
5388 	struct qelem *pnext = ppred->q_forw;
5389 
5390 	pelem->q_forw = pnext;
5391 	pelem->q_back = ppred;
5392 	ppred->q_forw = pelem;
5393 	pnext->q_back = pelem;
5394 }
5395 
5396 static void
5397 gldremque(void *arg)
5398 {
5399 	struct qelem *pelem = arg;
5400 	struct qelem *elem = arg;
5401 
5402 	pelem->q_forw->q_back = pelem->q_back;
5403 	pelem->q_back->q_forw = pelem->q_forw;
5404 	elem->q_back = elem->q_forw = NULL;
5405 }
5406 
5407 static gld_vlan_t *
5408 gld_add_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5409 {
5410 	gld_mac_pvt_t	*mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5411 	gld_vlan_t	**pp;
5412 	gld_vlan_t	*p;
5413 
5414 	pp = &(mac_pvt->vlan_hash[vid % VLAN_HASHSZ]);
5415 	while ((p = *pp) != NULL) {
5416 		ASSERT(p->gldv_id != vid);
5417 		pp = &(p->gldv_next);
5418 	}
5419 
5420 	if ((p = kmem_zalloc(sizeof (gld_vlan_t), KM_NOSLEEP)) == NULL)
5421 		return (NULL);
5422 
5423 	p->gldv_mac = macinfo;
5424 	p->gldv_id = vid;
5425 
5426 	if (vid == VLAN_VID_NONE) {
5427 		p->gldv_ptag = VLAN_VTAG_NONE;
5428 		p->gldv_stats = mac_pvt->statistics;
5429 		p->gldv_kstatp = NULL;
5430 	} else {
5431 		p->gldv_ptag = GLD_MK_PTAG(VLAN_CFI_ETHER, vid);
5432 		p->gldv_stats = kmem_zalloc(sizeof (struct gld_stats),
5433 		    KM_SLEEP);
5434 
5435 		if (gld_init_vlan_stats(p) != GLD_SUCCESS) {
5436 			kmem_free(p->gldv_stats, sizeof (struct gld_stats));
5437 			kmem_free(p, sizeof (gld_vlan_t));
5438 			return (NULL);
5439 		}
5440 	}
5441 
5442 	p->gldv_str_next = p->gldv_str_prev = (gld_t *)&p->gldv_str_next;
5443 	mac_pvt->nvlan++;
5444 	*pp = p;
5445 
5446 	return (p);
5447 }
5448 
5449 static void
5450 gld_rem_vlan(gld_vlan_t *vlan)
5451 {
5452 	gld_mac_info_t	*macinfo = vlan->gldv_mac;
5453 	gld_mac_pvt_t	*mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5454 	gld_vlan_t	**pp;
5455 	gld_vlan_t	*p;
5456 
5457 	pp = &(mac_pvt->vlan_hash[vlan->gldv_id % VLAN_HASHSZ]);
5458 	while ((p = *pp) != NULL) {
5459 		if (p->gldv_id == vlan->gldv_id)
5460 			break;
5461 		pp = &(p->gldv_next);
5462 	}
5463 	ASSERT(p != NULL);
5464 
5465 	*pp = p->gldv_next;
5466 	mac_pvt->nvlan--;
5467 	if (p->gldv_id != VLAN_VID_NONE) {
5468 		ASSERT(p->gldv_kstatp != NULL);
5469 		kstat_delete(p->gldv_kstatp);
5470 		kmem_free(p->gldv_stats, sizeof (struct gld_stats));
5471 	}
5472 	kmem_free(p, sizeof (gld_vlan_t));
5473 }
5474 
5475 gld_vlan_t *
5476 gld_find_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5477 {
5478 	gld_mac_pvt_t	*mac_pvt = (gld_mac_pvt_t *)macinfo->gldm_mac_pvt;
5479 	gld_vlan_t	*p;
5480 
5481 	p = mac_pvt->vlan_hash[vid % VLAN_HASHSZ];
5482 	while (p != NULL) {
5483 		if (p->gldv_id == vid)
5484 			return (p);
5485 		p = p->gldv_next;
5486 	}
5487 	return (NULL);
5488 }
5489 
5490 gld_vlan_t *
5491 gld_get_vlan(gld_mac_info_t *macinfo, uint32_t vid)
5492 {
5493 	gld_vlan_t	*vlan;
5494 
5495 	if ((vlan = gld_find_vlan(macinfo, vid)) == NULL)
5496 		vlan = gld_add_vlan(macinfo, vid);
5497 
5498 	return (vlan);
5499 }
5500 
5501 /*
5502  * gld_bitrevcopy()
5503  * This is essentially bcopy, with the ability to bit reverse the
5504  * the source bytes. The MAC addresses bytes as transmitted by FDDI
5505  * interfaces are bit reversed.
5506  */
5507 void
5508 gld_bitrevcopy(caddr_t src, caddr_t target, size_t n)
5509 {
5510 	while (n--)
5511 		*target++ = bit_rev[(uchar_t)*src++];
5512 }
5513 
5514 /*
5515  * gld_bitreverse()
5516  * Convert the bit order by swaping all the bits, using a
5517  * lookup table.
5518  */
5519 void
5520 gld_bitreverse(uchar_t *rptr, size_t n)
5521 {
5522 	while (n--) {
5523 		*rptr = bit_rev[*rptr];
5524 		rptr++;
5525 	}
5526 }
5527 
5528 char *
5529 gld_macaddr_sprintf(char *etherbuf, unsigned char *ap, int len)
5530 {
5531 	int i;
5532 	char *cp = etherbuf;
5533 	static char digits[] = "0123456789abcdef";
5534 
5535 	for (i = 0; i < len; i++) {
5536 		*cp++ = digits[*ap >> 4];
5537 		*cp++ = digits[*ap++ & 0xf];
5538 		*cp++ = ':';
5539 	}
5540 	*--cp = 0;
5541 	return (etherbuf);
5542 }
5543 
5544 #ifdef GLD_DEBUG
5545 static void
5546 gld_check_assertions()
5547 {
5548 	glddev_t	*dev;
5549 	gld_mac_info_t	*mac;
5550 	gld_t		*str;
5551 	gld_vlan_t	*vlan;
5552 	int		i;
5553 
5554 	mutex_enter(&gld_device_list.gld_devlock);
5555 
5556 	for (dev = gld_device_list.gld_next;
5557 	    dev != (glddev_t *)&gld_device_list.gld_next;
5558 	    dev = dev->gld_next) {
5559 		mutex_enter(&dev->gld_devlock);
5560 		ASSERT(dev->gld_broadcast != NULL);
5561 		for (str = dev->gld_str_next;
5562 		    str != (gld_t *)&dev->gld_str_next;
5563 		    str = str->gld_next) {
5564 			ASSERT(str->gld_device == dev);
5565 			ASSERT(str->gld_mac_info == NULL);
5566 			ASSERT(str->gld_qptr != NULL);
5567 			ASSERT(str->gld_minor >= GLD_MIN_CLONE_MINOR);
5568 			ASSERT(str->gld_multicnt == 0);
5569 			ASSERT(str->gld_mcast == NULL);
5570 			ASSERT(!(str->gld_flags &
5571 			    (GLD_PROM_PHYS|GLD_PROM_MULT|GLD_PROM_SAP)));
5572 			ASSERT(str->gld_sap == 0);
5573 			ASSERT(str->gld_state == DL_UNATTACHED);
5574 		}
5575 		for (mac = dev->gld_mac_next;
5576 		    mac != (gld_mac_info_t *)&dev->gld_mac_next;
5577 		    mac = mac->gldm_next) {
5578 			int nvlan = 0;
5579 			gld_mac_pvt_t *pvt = (gld_mac_pvt_t *)mac->gldm_mac_pvt;
5580 
5581 			if (!(mac->gldm_GLD_flags & GLD_MAC_READY))
5582 				continue;	/* this one's not ready yet */
5583 
5584 			GLDM_LOCK(mac, RW_WRITER);
5585 			ASSERT(mac->gldm_devinfo != NULL);
5586 			ASSERT(mac->gldm_mac_pvt != NULL);
5587 			ASSERT(pvt->interfacep != NULL);
5588 			ASSERT(pvt->kstatp != NULL);
5589 			ASSERT(pvt->statistics != NULL);
5590 			ASSERT(pvt->major_dev == dev);
5591 
5592 			for (i = 0; i < VLAN_HASHSZ; i++) {
5593 				for (vlan = pvt->vlan_hash[i];
5594 				    vlan != NULL; vlan = vlan->gldv_next) {
5595 					int nstr = 0;
5596 
5597 					ASSERT(vlan->gldv_mac == mac);
5598 
5599 					for (str = vlan->gldv_str_next;
5600 					    str !=
5601 					    (gld_t *)&vlan->gldv_str_next;
5602 					    str = str->gld_next) {
5603 						ASSERT(str->gld_device == dev);
5604 						ASSERT(str->gld_mac_info ==
5605 						    mac);
5606 						ASSERT(str->gld_qptr != NULL);
5607 						ASSERT(str->gld_minor >=
5608 						    GLD_MIN_CLONE_MINOR);
5609 						ASSERT(
5610 						    str->gld_multicnt == 0 ||
5611 						    str->gld_mcast);
5612 						nstr++;
5613 					}
5614 					ASSERT(vlan->gldv_nstreams == nstr);
5615 					nvlan++;
5616 				}
5617 			}
5618 			ASSERT(pvt->nvlan == nvlan);
5619 			GLDM_UNLOCK(mac);
5620 		}
5621 		mutex_exit(&dev->gld_devlock);
5622 	}
5623 	mutex_exit(&gld_device_list.gld_devlock);
5624 }
5625 #endif
5626