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