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