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