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