xref: /illumos-gate/usr/src/uts/common/io/usbgem/usbgem.c (revision 6dc983494b0ffef2565cc4d91371ee345425ffab)
1 /*
2  * usbgem.c: General USB to Fast Ethernet mac driver framework
3  *
4  * Copyright (c) 2002-2012 Masayuki Murayama.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of the author nor the names of its contributors may be
17  *    used to endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31  * DAMAGE.
32  */
33 
34 /*
35  * Copyright 2019 Joyent, Inc.
36  */
37 
38 /*
39  * Change log
40  */
41 
42 /*
43  * TODO:
44  *	implement DELAYED_START
45  */
46 
47 /*
48  * System Header files.
49  */
50 #include <sys/types.h>
51 #include <sys/conf.h>
52 #include <sys/debug.h>
53 #include <sys/kmem.h>
54 #include <sys/vtrace.h>
55 #include <sys/ethernet.h>
56 #include <sys/modctl.h>
57 #include <sys/errno.h>
58 #include <sys/ddi.h>
59 #include <sys/sunddi.h>
60 #include <sys/stream.h>		/* required for MBLK* */
61 #include <sys/strsun.h>		/* required for mionack() */
62 #include <sys/byteorder.h>
63 
64 #include <sys/usb/usba.h>
65 #include <inet/common.h>
66 #include <inet/led.h>
67 #include <inet/mi.h>
68 #include <inet/nd.h>
69 
70 /* supplement definitions */
71 extern const char *usb_str_cr(usb_cr_t);
72 
73 #include <sys/note.h>
74 
75 #include "usbgem_mii.h"
76 #include "usbgem.h"
77 
78 char	ident[] = "usb general ethernet mac driver v" VERSION;
79 
80 /* Debugging support */
81 #ifdef USBGEM_DEBUG_LEVEL
82 static int usbgem_debug = USBGEM_DEBUG_LEVEL;
83 #define	DPRINTF(n, args)	if (usbgem_debug > (n)) cmn_err args
84 #else
85 #define	DPRINTF(n, args)
86 #endif
87 
88 /*
89  * Useful macros and typedefs
90  */
91 #define	ROUNDUP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
92 #define	DEFAULT_PIPE(dp)	((dp)->reg_data->dev_default_ph)
93 #define	VTAG_SIZE	4
94 #define	BOOLEAN(x)	((x) != 0)
95 /*
96  * configuration parameters
97  */
98 #define	USBDRV_MAJOR_VER	2
99 #define	USBDRV_MINOR_VER	0
100 
101 #define	ETHERHEADERL	(sizeof (struct ether_header))
102 #define	MAXPKTLEN(dp)	((dp)->mtu + ETHERHEADERL)
103 #define	MAXPKTBUF(dp)	((dp)->mtu + ETHERHEADERL + ETHERFCSL)
104 
105 #define	WATCH_INTERVAL_FAST	drv_usectohz(100*1000)
106 
107 #define	STOP_GRACEFUL	B_TRUE
108 
109 /*
110  * Private functions
111  */
112 static int usbgem_open_pipes(struct usbgem_dev *dp);
113 static int usbgem_close_pipes(struct usbgem_dev *dp);
114 static void usbgem_intr_cb(usb_pipe_handle_t, usb_intr_req_t *);
115 static void usbgem_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *);
116 static void usbgem_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *);
117 
118 static int usbgem_mii_start(struct usbgem_dev *);
119 static void usbgem_mii_stop(struct usbgem_dev *);
120 
121 /* local buffer management */
122 static int usbgem_init_rx_buf(struct usbgem_dev *);
123 
124 /* internal mac interfaces */
125 static void usbgem_tx_timeout(struct usbgem_dev *);
126 static void usbgem_mii_link_watcher(struct usbgem_dev *);
127 static int usbgem_mac_init(struct usbgem_dev *);
128 static int usbgem_mac_start(struct usbgem_dev *);
129 static int usbgem_mac_stop(struct usbgem_dev *, int, boolean_t);
130 static void usbgem_mac_ioctl(struct usbgem_dev *, queue_t *, mblk_t *);
131 
132 int usbgem_speed_value[] = {10, 100, 1000};
133 
134 static int usbgem_ctrl_retry = 5;
135 
136 /* usb event support */
137 static int usbgem_disconnect_cb(dev_info_t *dip);
138 static int usbgem_reconnect_cb(dev_info_t *dip);
139 int usbgem_suspend(dev_info_t *dip);
140 int usbgem_resume(dev_info_t *dip);
141 
142 static uint8_t usbgem_bcastaddr[] = {
143 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
144 };
145 
146 extern struct mod_ops mod_miscops;
147 
148 static struct modlmisc modlmisc = {
149 	&mod_miscops,
150 	"usbgem v" VERSION,
151 };
152 
153 static struct modlinkage modlinkage = {
154 	MODREV_1, &modlmisc, NULL
155 };
156 
157 /*
158  * _init : done
159  */
160 int
161 _init(void)
162 {
163 	int	status;
164 
165 	DPRINTF(2, (CE_CONT, "!usbgem: _init: called"));
166 	status = mod_install(&modlinkage);
167 
168 	return (status);
169 }
170 
171 /*
172  * _fini : done
173  */
174 int
175 _fini(void)
176 {
177 	int	status;
178 
179 	DPRINTF(2, (CE_CONT, "!usbgem: _fini: called"));
180 	status = mod_remove(&modlinkage);
181 	return (status);
182 }
183 
184 int
185 _info(struct modinfo *modinfop)
186 {
187 	return (mod_info(&modlinkage, modinfop));
188 }
189 
190 /* ============================================================== */
191 /*
192  * Ether CRC calculation utilities
193  */
194 /* ============================================================== */
195 /*
196  * Ether CRC calculation according to 21143 data sheet
197  */
198 #define	CRC32_POLY_LE	0xedb88320
199 uint32_t
200 usbgem_ether_crc_le(const uint8_t *addr)
201 {
202 	int		idx;
203 	int		bit;
204 	uint_t		data;
205 	uint32_t	crc = 0xffffffff;
206 
207 	crc = 0xffffffff;
208 	for (idx = 0; idx < ETHERADDRL; idx++) {
209 		for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
210 			crc = (crc >> 1) ^
211 			    (((crc ^ data) & 1) ? CRC32_POLY_LE : 0);
212 		}
213 	}
214 	return	(crc);
215 }
216 
217 #define	CRC32_POLY_BE	0x04c11db7
218 uint32_t
219 usbgem_ether_crc_be(const uint8_t *addr)
220 {
221 	int		idx;
222 	int		bit;
223 	uint_t		data;
224 	uint32_t	crc;
225 
226 	crc = 0xffffffff;
227 	for (idx = 0; idx < ETHERADDRL; idx++) {
228 		for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
229 			crc = (crc << 1) ^
230 			    ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0);
231 		}
232 	}
233 	return (crc);
234 }
235 
236 int
237 usbgem_prop_get_int(struct usbgem_dev *dp, char *prop_template, int def_val)
238 {
239 	char	propname[32];
240 
241 	(void) sprintf(propname, prop_template, dp->name);
242 
243 	return (ddi_prop_get_int(DDI_DEV_T_ANY, dp->dip,
244 	    DDI_PROP_DONTPASS, propname, def_val));
245 }
246 
247 static int
248 usbgem_population(uint32_t x)
249 {
250 	int	i;
251 	int	cnt;
252 
253 	cnt = 0;
254 	for (i = 0; i < 32; i++) {
255 		if (x & (1 << i)) {
256 			cnt++;
257 		}
258 	}
259 	return (cnt);
260 }
261 
262 static clock_t
263 usbgem_timestamp_nz()
264 {
265 	clock_t	now;
266 	now = ddi_get_lbolt();
267 	return (now ? now : (clock_t)1);
268 }
269 
270 #ifdef USBGEM_DEBUG_LEVEL
271 #ifdef USBGEM_DEBUG_VLAN
272 #ifdef notdef
273 #include <netinet/in.h>
274 #endif
275 static void
276 usbgem_dump_packet(struct usbgem_dev *dp, char *title, mblk_t *mp,
277     boolean_t check_cksum)
278 {
279 	char	msg[180];
280 	uint8_t	buf[18+20+20];
281 	uint8_t	*p;
282 	size_t	offset;
283 	uint_t	ethertype;
284 	uint_t	proto;
285 	uint_t	ipproto = 0;
286 	uint_t	iplen;
287 	uint_t	iphlen;
288 	uint_t	tcplen;
289 	uint_t	udplen;
290 	uint_t	cksum;
291 	int	rest;
292 	int	len;
293 	char	*bp;
294 	mblk_t	*tp;
295 	extern uint_t	ip_cksum(mblk_t *, int, uint32_t);
296 
297 	msg[0] = 0;
298 	bp = msg;
299 
300 	rest = sizeof (buf);
301 	offset = 0;
302 	for (tp = mp; tp; tp = tp->b_cont) {
303 		len = tp->b_wptr - tp->b_rptr;
304 		len = min(rest, len);
305 		bcopy(tp->b_rptr, &buf[offset], len);
306 		rest -= len;
307 		offset += len;
308 		if (rest == 0) {
309 			break;
310 		}
311 	}
312 
313 	offset = 0;
314 	p = &buf[offset];
315 
316 	/* ethernet address */
317 	sprintf(bp,
318 	    "ether: %02x:%02x:%02x:%02x:%02x:%02x"
319 	    " -> %02x:%02x:%02x:%02x:%02x:%02x",
320 	    p[6], p[7], p[8], p[9], p[10], p[11],
321 	    p[0], p[1], p[2], p[3], p[4], p[5]);
322 	bp = &msg[strlen(msg)];
323 
324 	/* vlag tag and etherrtype */
325 	ethertype = GET_ETHERTYPE(p);
326 	if (ethertype == VTAG_TPID) {
327 		sprintf(bp, " vtag:0x%04x", GET_NET16(&p[14]));
328 		bp = &msg[strlen(msg)];
329 
330 		offset += VTAG_SIZE;
331 		p = &buf[offset];
332 		ethertype = GET_ETHERTYPE(p);
333 	}
334 	sprintf(bp, " type:%04x", ethertype);
335 	bp = &msg[strlen(msg)];
336 
337 	/* ethernet packet length */
338 	sprintf(bp, " mblklen:%d", msgdsize(mp));
339 	bp = &msg[strlen(msg)];
340 	if (mp->b_cont) {
341 		sprintf(bp, "(");
342 		bp = &msg[strlen(msg)];
343 		for (tp = mp; tp; tp = tp->b_cont) {
344 			if (tp == mp) {
345 				sprintf(bp, "%d", tp->b_wptr - tp->b_rptr);
346 			} else {
347 				sprintf(bp, "+%d", tp->b_wptr - tp->b_rptr);
348 			}
349 			bp = &msg[strlen(msg)];
350 		}
351 		sprintf(bp, ")");
352 		bp = &msg[strlen(msg)];
353 	}
354 
355 	if (ethertype != ETHERTYPE_IP) {
356 		goto x;
357 	}
358 
359 	/* ip address */
360 	offset += sizeof (struct ether_header);
361 	p = &buf[offset];
362 	ipproto = p[9];
363 	iplen = GET_NET16(&p[2]);
364 	sprintf(bp, ", ip: %d.%d.%d.%d -> %d.%d.%d.%d proto:%d iplen:%d",
365 	    p[12], p[13], p[14], p[15],
366 	    p[16], p[17], p[18], p[19],
367 	    ipproto, iplen);
368 	bp = (void *)&msg[strlen(msg)];
369 
370 	iphlen = (p[0] & 0xf) * 4;
371 
372 	/* cksum for psuedo header */
373 	cksum = *(uint16_t *)&p[12];
374 	cksum += *(uint16_t *)&p[14];
375 	cksum += *(uint16_t *)&p[16];
376 	cksum += *(uint16_t *)&p[18];
377 	cksum += BE_16(ipproto);
378 
379 	/* tcp or udp protocol header */
380 	offset += iphlen;
381 	p = &buf[offset];
382 	if (ipproto == IPPROTO_TCP) {
383 		tcplen = iplen - iphlen;
384 		sprintf(bp, ", tcp: len:%d cksum:%x",
385 		    tcplen, GET_NET16(&p[16]));
386 		bp = (void *)&msg[strlen(msg)];
387 
388 		if (check_cksum) {
389 			cksum += BE_16(tcplen);
390 			cksum = (uint16_t)ip_cksum(mp, offset, cksum);
391 			sprintf(bp, " (%s)",
392 			    (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
393 			bp = (void *)&msg[strlen(msg)];
394 		}
395 	} else if (ipproto == IPPROTO_UDP) {
396 		udplen = GET_NET16(&p[4]);
397 		sprintf(bp, ", udp: len:%d cksum:%x",
398 		    udplen, GET_NET16(&p[6]));
399 		bp = (void *)&msg[strlen(msg)];
400 
401 		if (GET_NET16(&p[6]) && check_cksum) {
402 			cksum += *(uint16_t *)&p[4];
403 			cksum = (uint16_t)ip_cksum(mp, offset, cksum);
404 			sprintf(bp, " (%s)",
405 			    (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
406 			bp = (void *)&msg[strlen(msg)];
407 		}
408 	}
409 x:
410 	cmn_err(CE_CONT, "!%s: %s: %s", dp->name, title, msg);
411 }
412 #endif /* USBGEM_DEBUG_VLAN */
413 #endif /* USBGEM_DEBUG_LEVEL */
414 
415 /* ============================================================== */
416 /*
417  * hardware operations
418  */
419 /* ============================================================== */
420 static int
421 usbgem_hal_reset_chip(struct usbgem_dev *dp)
422 {
423 	int	err;
424 
425 	sema_p(&dp->hal_op_lock);
426 	err = (*dp->ugc.usbgc_reset_chip)(dp);
427 	sema_v(&dp->hal_op_lock);
428 	return (err);
429 }
430 
431 static int
432 usbgem_hal_init_chip(struct usbgem_dev *dp)
433 {
434 	int	err;
435 
436 	sema_p(&dp->hal_op_lock);
437 	err = (*dp->ugc.usbgc_init_chip)(dp);
438 	sema_v(&dp->hal_op_lock);
439 	return (err);
440 }
441 
442 static int
443 usbgem_hal_attach_chip(struct usbgem_dev *dp)
444 {
445 	int	err;
446 
447 	sema_p(&dp->hal_op_lock);
448 	err = (*dp->ugc.usbgc_attach_chip)(dp);
449 	sema_v(&dp->hal_op_lock);
450 	return (err);
451 }
452 
453 static int
454 usbgem_hal_set_rx_filter(struct usbgem_dev *dp)
455 {
456 	int	err;
457 
458 	sema_p(&dp->hal_op_lock);
459 	err = (*dp->ugc.usbgc_set_rx_filter)(dp);
460 	sema_v(&dp->hal_op_lock);
461 	return (err);
462 }
463 
464 static int
465 usbgem_hal_set_media(struct usbgem_dev *dp)
466 {
467 	int	err;
468 
469 	sema_p(&dp->hal_op_lock);
470 	err = (*dp->ugc.usbgc_set_media)(dp);
471 	sema_v(&dp->hal_op_lock);
472 	return (err);
473 }
474 
475 static int
476 usbgem_hal_start_chip(struct usbgem_dev *dp)
477 {
478 	int	err;
479 
480 	sema_p(&dp->hal_op_lock);
481 	err = (*dp->ugc.usbgc_start_chip)(dp);
482 	sema_v(&dp->hal_op_lock);
483 	return (err);
484 }
485 
486 static int
487 usbgem_hal_stop_chip(struct usbgem_dev *dp)
488 {
489 	int	err;
490 
491 	sema_p(&dp->hal_op_lock);
492 	err = (*dp->ugc.usbgc_stop_chip)(dp);
493 	sema_v(&dp->hal_op_lock);
494 	return (err);
495 }
496 
497 static int
498 usbgem_hal_get_stats(struct usbgem_dev *dp)
499 {
500 	int	err;
501 
502 	sema_p(&dp->hal_op_lock);
503 	err = (*dp->ugc.usbgc_get_stats)(dp);
504 	sema_v(&dp->hal_op_lock);
505 	return (err);
506 }
507 
508 
509 /* ============================================================== */
510 /*
511  * USB pipe management
512  */
513 /* ============================================================== */
514 static boolean_t
515 usbgem_rx_start_unit(struct usbgem_dev *dp, usb_bulk_req_t *req)
516 {
517 	mblk_t	*mp;
518 	int	err;
519 	usb_flags_t	flags;
520 
521 	ASSERT(req);
522 
523 	mp = allocb(dp->rx_buf_len, BPRI_MED);
524 	if (mp == NULL) {
525 		cmn_err(CE_WARN, "!%s: %s: failed to allocate mblk",
526 		    dp->name, __func__);
527 		goto err;
528 	}
529 
530 	req->bulk_len = dp->rx_buf_len;
531 	req->bulk_data = mp;
532 	req->bulk_client_private = (usb_opaque_t)dp;
533 	req->bulk_timeout = 0;
534 	req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK;
535 	req->bulk_cb = usbgem_bulkin_cb;
536 	req->bulk_exc_cb = usbgem_bulkin_cb;
537 	req->bulk_completion_reason = 0;
538 	req->bulk_cb_flags = 0;
539 
540 	flags = 0;
541 	err = usb_pipe_bulk_xfer(dp->bulkin_pipe, req, flags);
542 
543 	if (err != USB_SUCCESS) {
544 		cmn_err(CE_WARN, "%s: failed to bulk_xfer for rx, err:%d",
545 		    dp->name, err);
546 
547 		/* free req and mp */
548 		usb_free_bulk_req(req);
549 		goto err;
550 	}
551 	return (B_TRUE);
552 err:
553 	return (B_FALSE);
554 }
555 
556 /* ============================================================== */
557 /*
558  * Rx/Tx buffer management
559  */
560 /* ============================================================== */
561 static int
562 usbgem_init_rx_buf(struct usbgem_dev *dp)
563 {
564 	int	i;
565 	usb_bulk_req_t	*req;
566 
567 	ASSERT(dp->mac_state == MAC_STATE_ONLINE);
568 
569 	for (i = 0; i < dp->ugc.usbgc_rx_list_max; i++) {
570 		req = usb_alloc_bulk_req(dp->dip, 0, USB_FLAGS_SLEEP);
571 		if (req == NULL) {
572 			cmn_err(CE_WARN,
573 			    "!%s: %s: failed to allocate bulkreq for rx",
574 			    dp->name, __func__);
575 			return (USB_FAILURE);
576 		}
577 		if (!usbgem_rx_start_unit(dp, req)) {
578 			return (USB_FAILURE);
579 		}
580 		mutex_enter(&dp->rxlock);
581 		dp->rx_busy_cnt++;
582 		mutex_exit(&dp->rxlock);
583 	}
584 	return (USB_SUCCESS);
585 }
586 
587 /* ============================================================== */
588 /*
589  * memory resource management
590  */
591 /* ============================================================== */
592 static int
593 usbgem_free_memory(struct usbgem_dev *dp)
594 {
595 	usb_bulk_req_t	*req;
596 
597 	/* free all tx requst structure */
598 	while ((req = dp->tx_free_list) != NULL) {
599 		dp->tx_free_list =
600 		    (usb_bulk_req_t *)req->bulk_client_private;
601 		req->bulk_data = NULL;
602 		usb_free_bulk_req(req);
603 	}
604 	return (USB_SUCCESS);
605 }
606 
607 static int
608 usbgem_alloc_memory(struct usbgem_dev *dp)
609 {
610 	int	i;
611 	usb_bulk_req_t	*req;
612 
613 	/* allocate tx requests */
614 	dp->tx_free_list = NULL;
615 	for (i = 0; i < dp->ugc.usbgc_tx_list_max; i++) {
616 		req = usb_alloc_bulk_req(dp->dip, 0, USB_FLAGS_SLEEP);
617 		if (req == NULL) {
618 			cmn_err(CE_WARN,
619 			    "%s:%s failed to allocate tx requests",
620 			    dp->name, __func__);
621 
622 			/* free partially allocated tx requests */
623 			(void) usbgem_free_memory(dp);
624 			return (USB_FAILURE);
625 		}
626 
627 		/* add the new one allocated into tx free list */
628 		req->bulk_client_private = (usb_opaque_t)dp->tx_free_list;
629 		dp->tx_free_list = req;
630 	}
631 
632 	return (USB_SUCCESS);
633 }
634 
635 /* ========================================================== */
636 /*
637  * Start transmission.
638  * Return zero on success,
639  */
640 /* ========================================================== */
641 
642 #ifdef TXTIMEOUT_TEST
643 static int usbgem_send_cnt = 0;
644 #endif
645 
646 /*
647  * usbgem_send is used only to send data packet into ethernet line.
648  */
649 static mblk_t *
650 usbgem_send_common(struct usbgem_dev *dp, mblk_t *mp, uint32_t flags)
651 {
652 	int		err;
653 	mblk_t		*new;
654 	usb_bulk_req_t	*req;
655 	int		mcast;
656 	int		bcast;
657 	int		len;
658 	boolean_t	intr;
659 	usb_flags_t	usb_flags = 0;
660 #ifdef USBGEM_DEBUG_LEVEL
661 	usb_pipe_state_t	p_state;
662 #endif
663 	DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__));
664 
665 	intr = (flags & 1) != 0;
666 	len = msgdsize(mp);
667 	bcast = 0;
668 	mcast = 0;
669 	if (mp->b_rptr[0] & 1) {
670 		if (bcmp(mp->b_rptr, &usbgem_bcastaddr, ETHERADDRL) == 0) {
671 			bcast = 1;
672 		} else {
673 			mcast = 1;
674 		}
675 	}
676 	new = (*dp->ugc.usbgc_tx_make_packet)(dp, mp);
677 	if (new == NULL) {
678 		/*
679 		 * no memory resource. we don't stop downstream,
680 		 * we just discard the packet.
681 		 */
682 		DPRINTF(0, (CE_CONT, "!%s: %s: no memory",
683 		    dp->name, __func__));
684 		freemsg(mp);
685 
686 		mutex_enter(&dp->txlock);
687 		dp->stats.noxmtbuf++;
688 		dp->stats.errxmt++;
689 		mutex_exit(&dp->txlock);
690 
691 		return (NULL);
692 	}
693 
694 	ASSERT(new->b_cont == NULL);
695 
696 	mutex_enter(&dp->txlock);
697 	if (dp->tx_free_list == NULL) {
698 		/*
699 		 * no tx free slot
700 		 */
701 		ASSERT(dp->tx_busy_cnt == dp->ugc.usbgc_tx_list_max);
702 		mutex_exit(&dp->txlock);
703 
704 		DPRINTF(4, (CE_CONT, "!%s: %s: no free slot",
705 		    dp->name, __func__));
706 		if (new && new != mp) {
707 			/* free reallocated message */
708 			freemsg(new);
709 		}
710 		return (mp);
711 	}
712 	req = dp->tx_free_list;
713 	dp->tx_free_list = (usb_bulk_req_t *)req->bulk_client_private;
714 	dp->tx_busy_cnt++;
715 
716 	if (dp->tx_free_list == NULL) {
717 		intr = B_TRUE;
718 	}
719 	if (intr) {
720 		dp->tx_intr_pended++;
721 	}
722 	DB_TCI(new) = intr;
723 #ifdef USBGEM_DEBUG_LEVEL
724 	new->b_datap->db_cksum32 = dp->tx_seq_num;
725 	dp->tx_seq_num++;
726 #endif
727 	dp->stats.obytes += len;
728 	dp->stats.opackets++;
729 	if (bcast | mcast) {
730 		dp->stats.obcast += bcast;
731 		dp->stats.omcast += mcast;
732 	}
733 	mutex_exit(&dp->txlock);
734 
735 	DPRINTF(2, (CE_CONT, "!%s: %s: sending", dp->name, __func__));
736 
737 	req->bulk_len = (long)new->b_wptr - (long)new->b_rptr;
738 	req->bulk_data = new;
739 	req->bulk_client_private = (usb_opaque_t)dp;
740 	req->bulk_timeout = dp->bulkout_timeout;	/* in second */
741 	req->bulk_attributes = 0;
742 	req->bulk_cb = usbgem_bulkout_cb;
743 	req->bulk_exc_cb = usbgem_bulkout_cb;
744 	req->bulk_completion_reason = 0;
745 	req->bulk_cb_flags = 0;
746 
747 	if (intr) {
748 		usb_flags = USB_FLAGS_SLEEP;
749 	}
750 	if ((err = usb_pipe_bulk_xfer(dp->bulkout_pipe, req, usb_flags))
751 	    != USB_SUCCESS) {
752 
753 		/* failed to transfer the packet, discard it. */
754 		freemsg(new);
755 		req->bulk_data = NULL;
756 
757 		/* recycle the request block */
758 		mutex_enter(&dp->txlock);
759 		dp->tx_busy_cnt--;
760 		req->bulk_client_private = (usb_opaque_t)dp->tx_free_list;
761 		dp->tx_free_list = req;
762 		mutex_exit(&dp->txlock);
763 
764 		cmn_err(CE_NOTE,
765 		    "%s: %s: usb_pipe_bulk_xfer: failed: err:%d",
766 		    dp->name, __func__, err);
767 
768 		/* we use another flag to indicate error state. */
769 		if (dp->fatal_error == (clock_t)0) {
770 			dp->fatal_error = usbgem_timestamp_nz();
771 		}
772 	} else {
773 		/* record the start time */
774 		dp->tx_start_time = ddi_get_lbolt();
775 	}
776 
777 	if (err == USB_SUCCESS && (usb_flags & USB_FLAGS_SLEEP)) {
778 		usbgem_bulkout_cb(dp->bulkout_pipe, req);
779 	}
780 
781 	if (new != mp) {
782 		freemsg(mp);
783 	}
784 	return (NULL);
785 }
786 
787 int
788 usbgem_restart_nic(struct usbgem_dev *dp)
789 {
790 	int	ret;
791 	int	flags = 0;
792 
793 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
794 
795 	ASSERT(dp->mac_state != MAC_STATE_DISCONNECTED);
796 
797 	/*
798 	 * ensure to stop the nic
799 	 */
800 	if (dp->mac_state == MAC_STATE_ONLINE) {
801 		(void) usbgem_mac_stop(dp, MAC_STATE_STOPPED, STOP_GRACEFUL);
802 	}
803 
804 	/* now the nic become quiescent, reset the chip */
805 	if (usbgem_hal_reset_chip(dp) != USB_SUCCESS) {
806 		cmn_err(CE_WARN, "%s: %s: failed to reset chip",
807 		    dp->name, __func__);
808 		goto err;
809 	}
810 
811 	/*
812 	 * restore the nic state step by step
813 	 */
814 	if (dp->nic_state < NIC_STATE_INITIALIZED) {
815 		goto done;
816 	}
817 
818 	if (usbgem_mac_init(dp) != USB_SUCCESS) {
819 		cmn_err(CE_WARN, "%s: %s: failed to initialize chip",
820 		    dp->name, __func__);
821 		goto err;
822 	}
823 
824 	/* setup mac address and enable rx filter */
825 	sema_p(&dp->rxfilter_lock);
826 	dp->rxmode |= RXMODE_ENABLE;
827 	ret = usbgem_hal_set_rx_filter(dp);
828 	sema_v(&dp->rxfilter_lock);
829 	if (ret != USB_SUCCESS) {
830 		goto err;
831 	}
832 
833 	/*
834 	 * update the link state asynchronously
835 	 */
836 	cv_signal(&dp->link_watcher_wait_cv);
837 
838 	/*
839 	 * XXX - a panic happened because of linkdown.
840 	 * We must check mii_state here, because the link can be down just
841 	 * before the restart event happen. If the link is down now,
842 	 * gem_mac_start() will be called from gem_mii_link_check() when
843 	 * the link become up later.
844 	 */
845 	if (dp->mii_state == MII_STATE_LINKUP) {
846 		if (usbgem_hal_set_media(dp) != USB_SUCCESS) {
847 			goto err;
848 		}
849 		if (dp->nic_state < NIC_STATE_ONLINE) {
850 			goto done;
851 		}
852 
853 		(void) usbgem_mac_start(dp);
854 
855 	}
856 done:
857 	return (USB_SUCCESS);
858 err:
859 #ifdef GEM_CONFIG_FMA
860 	ddi_fm_service_impact(dp->dip, DDI_SERVICE_DEGRADED);
861 #endif
862 	return (USB_FAILURE);
863 }
864 
865 static void
866 usbgem_tx_timeout(struct usbgem_dev *dp)
867 {
868 	uint_t	rwlock;
869 	clock_t	now;
870 
871 	for (; ; ) {
872 		mutex_enter(&dp->tx_watcher_lock);
873 		(void) cv_timedwait(&dp->tx_watcher_cv, &dp->tx_watcher_lock,
874 		    dp->tx_watcher_interval + ddi_get_lbolt());
875 		mutex_exit(&dp->tx_watcher_lock);
876 
877 		if (dp->tx_watcher_stop) {
878 			break;
879 		}
880 
881 		now = ddi_get_lbolt();
882 
883 		rwlock = RW_READER;
884 again:
885 		rw_enter(&dp->dev_state_lock, rwlock);
886 
887 		if ((dp->mac_state != MAC_STATE_DISCONNECTED &&
888 		    dp->fatal_error &&
889 		    now - dp->fatal_error >= dp->ugc.usbgc_tx_timeout) ||
890 		    (dp->mac_state == MAC_STATE_ONLINE &&
891 		    dp->mii_state == MII_STATE_LINKUP &&
892 		    dp->tx_busy_cnt != 0 &&
893 		    now - dp->tx_start_time >= dp->ugc.usbgc_tx_timeout)) {
894 			if (rwlock == RW_READER) {
895 				/*
896 				 * Upgrade dev_state_lock from shared mode
897 				 * to exclusive mode to restart nic
898 				 */
899 				rwlock = RW_WRITER;
900 				rw_exit(&dp->dev_state_lock);
901 				goto again;
902 			}
903 			cmn_err(CE_WARN, "%s: %s: restarting the nic:"
904 			    " fatal_error:%ld nic_state:%d"
905 			    " mac_state:%d starttime:%ld",
906 			    dp->name, __func__,
907 			    dp->fatal_error ? now - dp->fatal_error: 0,
908 			    dp->nic_state, dp->mac_state,
909 			    dp->tx_busy_cnt ? now - dp->tx_start_time : 0);
910 
911 			(void) usbgem_restart_nic(dp);
912 		}
913 
914 		rw_exit(&dp->dev_state_lock);
915 	}
916 }
917 
918 static int
919 usbgem_tx_watcher_start(struct usbgem_dev *dp)
920 {
921 	int	err;
922 	kthread_t	*wdth;
923 
924 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
925 
926 	/* make a first call of uwgem_lw_link_check() */
927 	dp->tx_watcher_stop = 0;
928 	dp->tx_watcher_interval = drv_usectohz(1000*1000);
929 
930 	wdth = thread_create(NULL, 0, usbgem_tx_timeout, dp, 0, &p0,
931 	    TS_RUN, minclsyspri);
932 	if (wdth == NULL) {
933 		cmn_err(CE_WARN,
934 		    "!%s: %s: failed to create a tx_watcher thread",
935 		    dp->name, __func__);
936 		return (USB_FAILURE);
937 	}
938 	dp->tx_watcher_did = wdth->t_did;
939 
940 	return (USB_SUCCESS);
941 }
942 
943 static void
944 usbgem_tx_watcher_stop(struct usbgem_dev *dp)
945 {
946 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
947 	if (dp->tx_watcher_did) {
948 		/* Ensure timer routine stopped */
949 		dp->tx_watcher_stop = 1;
950 		cv_signal(&dp->tx_watcher_cv);
951 		thread_join(dp->tx_watcher_did);
952 		dp->tx_watcher_did = 0;
953 	}
954 }
955 
956 /* ================================================================== */
957 /*
958  * Callback handlers
959  */
960 /* ================================================================== */
961 static void
962 usbgem_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
963 {
964 	mblk_t	*newmp;
965 	mblk_t	*mp;
966 	mblk_t	*tp;
967 	uint64_t	len = 0;
968 	int	pkts = 0;
969 	int	bcast = 0;
970 	int	mcast = 0;
971 	boolean_t	busy;
972 	struct usbgem_dev	*dp;
973 
974 	dp = (struct usbgem_dev *)req->bulk_client_private;
975 	mp = req->bulk_data;
976 	req->bulk_data = NULL;
977 
978 	DPRINTF(2, (CE_CONT, "!%s: %s: mp:%p, cr:%s(%d)",
979 	    dp->name, __func__, mp,
980 	    usb_str_cr(req->bulk_completion_reason),
981 	    req->bulk_completion_reason));
982 
983 	/*
984 	 * we cannot acquire dev_state_lock because the routine
985 	 * must be executed during usbgem_mac_stop() to avoid
986 	 * dead lock.
987 	 * we use a simle membar operation to get the state correctly.
988 	 */
989 	membar_consumer();
990 
991 	if (req->bulk_completion_reason == USB_CR_OK &&
992 	    dp->nic_state == NIC_STATE_ONLINE) {
993 		newmp = (*dp->ugc.usbgc_rx_make_packet)(dp, mp);
994 
995 		if (newmp != mp) {
996 			/* the message has been reallocated, free old one */
997 			freemsg(mp);
998 		}
999 
1000 		/* the message may includes one or more ethernet packets */
1001 		for (tp = newmp; tp; tp = tp->b_next) {
1002 			len += (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr;
1003 			pkts++;
1004 			if (tp->b_rptr[0] & 1) {
1005 				if (bcmp(tp->b_rptr, &usbgem_bcastaddr,
1006 				    ETHERADDRL) == 0) {
1007 					bcast++;
1008 				} else {
1009 					mcast++;
1010 				}
1011 			}
1012 		}
1013 
1014 		/* send up if it is a valid packet */
1015 		mac_rx(dp->mh, NULL, newmp);
1016 	} else {
1017 		freemsg(mp);
1018 		len = 0;
1019 	}
1020 
1021 	mutex_enter(&dp->rxlock);
1022 	/* update rx_active */
1023 	if (dp->rx_active) {
1024 		dp->rx_active = dp->mac_state == MAC_STATE_ONLINE;
1025 	}
1026 
1027 	dp->stats.rbytes += len;
1028 	dp->stats.rpackets += pkts;
1029 	if (bcast | mcast) {
1030 		dp->stats.rbcast += bcast;
1031 		dp->stats.rmcast += mcast;
1032 	}
1033 	mutex_exit(&dp->rxlock);
1034 
1035 	if (dp->rx_active) {
1036 		/* prepare to receive the next packets */
1037 		if (usbgem_rx_start_unit(dp, req)) {
1038 			/* we successed */
1039 			goto done;
1040 		}
1041 		cmn_err(CE_WARN,
1042 		    "!%s: %s: failed to fill next rx packet",
1043 		    dp->name, __func__);
1044 		/*
1045 		 * we use another flag to indicate error state.
1046 		 * if we acquire dev_state_lock for RW_WRITER here,
1047 		 * usbgem_mac_stop() may hang.
1048 		 */
1049 		if (dp->fatal_error == (clock_t)0) {
1050 			dp->fatal_error = usbgem_timestamp_nz();
1051 		}
1052 	} else {
1053 		/* no need to prepare the next packets */
1054 		usb_free_bulk_req(req);
1055 	}
1056 
1057 	mutex_enter(&dp->rxlock);
1058 	dp->rx_active = B_FALSE;
1059 	dp->rx_busy_cnt--;
1060 	if (dp->rx_busy_cnt == 0) {
1061 		/* wake up someone waits for me */
1062 		cv_broadcast(&dp->rx_drain_cv);
1063 	}
1064 	mutex_exit(&dp->rxlock);
1065 done:
1066 	;
1067 }
1068 
1069 static void
1070 usbgem_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1071 {
1072 	boolean_t	intr;
1073 	boolean_t	tx_sched;
1074 	struct usbgem_dev	*dp;
1075 
1076 	dp = (struct usbgem_dev *)req->bulk_client_private;
1077 	tx_sched = B_FALSE;
1078 
1079 	DPRINTF(2, (CE_CONT,
1080 	    "!%s: %s: cr:%s(%d) cb_flags:0x%x head:%d tail:%d",
1081 	    dp->name, __func__,
1082 	    usb_str_cr(req->bulk_completion_reason),
1083 	    req->bulk_completion_reason,
1084 	    req->bulk_cb_flags,
1085 	    dp->tx_busy_cnt));
1086 
1087 	/* we have finished to transfer the packet into tx fifo */
1088 	intr = DB_TCI(req->bulk_data);
1089 	freemsg(req->bulk_data);
1090 
1091 	if (req->bulk_completion_reason != USB_CR_OK &&
1092 	    dp->fatal_error == (clock_t)0) {
1093 		dp->fatal_error = usbgem_timestamp_nz();
1094 	}
1095 
1096 	mutex_enter(&dp->txlock);
1097 
1098 	if (intr) {
1099 		ASSERT(dp->tx_intr_pended > 0);
1100 		/* find the last interrupt we have scheduled */
1101 		if (--(dp->tx_intr_pended) == 0) {
1102 			tx_sched = B_TRUE;
1103 		}
1104 	}
1105 
1106 	ASSERT(dp->tx_busy_cnt > 0);
1107 	req->bulk_client_private = (usb_opaque_t)dp->tx_free_list;
1108 	dp->tx_free_list = req;
1109 	dp->tx_busy_cnt--;
1110 
1111 #ifdef CONFIG_TX_LIMITER
1112 	if (tx_sched) {
1113 		dp->tx_max_packets =
1114 		    min(dp->tx_max_packets + 1, dp->ugc.usbgc_tx_list_max);
1115 	}
1116 #endif
1117 	if (dp->mac_state != MAC_STATE_ONLINE && dp->tx_busy_cnt == 0) {
1118 		cv_broadcast(&dp->tx_drain_cv);
1119 	}
1120 
1121 	mutex_exit(&dp->txlock);
1122 
1123 	if (tx_sched) {
1124 		mac_tx_update(dp->mh);
1125 	}
1126 }
1127 
1128 static void
1129 usbgem_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req)
1130 {
1131 	struct usbgem_dev	*dp;
1132 
1133 	dp = (struct usbgem_dev *)req->intr_client_private;
1134 	dp->stats.intr++;
1135 
1136 	if (req->intr_completion_reason == USB_CR_OK) {
1137 		(*dp->ugc.usbgc_interrupt)(dp, req->intr_data);
1138 	}
1139 
1140 	/* free the request and data */
1141 	usb_free_intr_req(req);
1142 }
1143 
1144 /* ======================================================================== */
1145 /*
1146  * MII support routines
1147  */
1148 /* ======================================================================== */
1149 static void
1150 usbgem_choose_forcedmode(struct usbgem_dev *dp)
1151 {
1152 	/* choose media mode */
1153 	if (dp->anadv_1000fdx || dp->anadv_1000hdx) {
1154 		dp->speed = USBGEM_SPD_1000;
1155 		dp->full_duplex = dp->anadv_1000fdx;
1156 	} else if (dp->anadv_100fdx || dp->anadv_100t4) {
1157 		dp->speed = USBGEM_SPD_100;
1158 		dp->full_duplex = B_TRUE;
1159 	} else if (dp->anadv_100hdx) {
1160 		dp->speed = USBGEM_SPD_100;
1161 		dp->full_duplex = B_FALSE;
1162 	} else {
1163 		dp->speed = USBGEM_SPD_10;
1164 		dp->full_duplex = dp->anadv_10fdx;
1165 	}
1166 }
1167 
1168 static uint16_t
1169 usbgem_mii_read(struct usbgem_dev *dp, uint_t reg, int *errp)
1170 {
1171 	uint16_t	val;
1172 
1173 	sema_p(&dp->hal_op_lock);
1174 	val = (*dp->ugc.usbgc_mii_read)(dp, reg, errp);
1175 	sema_v(&dp->hal_op_lock);
1176 
1177 	return (val);
1178 }
1179 
1180 static void
1181 usbgem_mii_write(struct usbgem_dev *dp, uint_t reg, uint16_t val, int *errp)
1182 {
1183 	sema_p(&dp->hal_op_lock);
1184 	(*dp->ugc.usbgc_mii_write)(dp, reg, val, errp);
1185 	sema_v(&dp->hal_op_lock);
1186 }
1187 
1188 static int
1189 usbgem_mii_probe(struct usbgem_dev *dp)
1190 {
1191 	int	err;
1192 
1193 	err = (*dp->ugc.usbgc_mii_probe)(dp);
1194 	return (err);
1195 }
1196 
1197 static int
1198 usbgem_mii_init(struct usbgem_dev *dp)
1199 {
1200 	int	err;
1201 
1202 	err = (*dp->ugc.usbgc_mii_init)(dp);
1203 	return (err);
1204 }
1205 
1206 #define	fc_cap_decode(x)	\
1207 	((((x) & MII_ABILITY_PAUSE) != 0 ? 1 : 0) |	\
1208 	(((x) & MII_ABILITY_ASM_DIR) != 0 ? 2 : 0))
1209 
1210 int
1211 usbgem_mii_config_default(struct usbgem_dev *dp, int *errp)
1212 {
1213 	uint16_t	mii_stat;
1214 	uint16_t	val;
1215 
1216 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
1217 
1218 	/*
1219 	 * Configure bits in advertisement register
1220 	 */
1221 	mii_stat = dp->mii_status;
1222 
1223 	DPRINTF(1, (CE_CONT, "!%s: %s: MII_STATUS reg:%b",
1224 	    dp->name, __func__, mii_stat, MII_STATUS_BITS));
1225 
1226 	if ((mii_stat & MII_STATUS_ABILITY_TECH) == 0) {
1227 		/* it's funny */
1228 		cmn_err(CE_WARN, "!%s: wrong ability bits: mii_status:%b",
1229 		    dp->name, mii_stat, MII_STATUS_BITS);
1230 		return (USB_FAILURE);
1231 	}
1232 
1233 	/* Do not change the rest of ability bits in advert reg */
1234 	val = usbgem_mii_read(dp, MII_AN_ADVERT, errp) & ~MII_ABILITY_ALL;
1235 	if (*errp != USB_SUCCESS) {
1236 		goto usberr;
1237 	}
1238 
1239 	DPRINTF(0, (CE_CONT,
1240 	    "!%s: %s: 100T4:%d 100F:%d 100H:%d 10F:%d 10H:%d",
1241 	    dp->name, __func__,
1242 	    dp->anadv_100t4, dp->anadv_100fdx, dp->anadv_100hdx,
1243 	    dp->anadv_10fdx, dp->anadv_10hdx));
1244 
1245 	/* set technology bits */
1246 	if (dp->anadv_100t4) {
1247 		val |= MII_ABILITY_100BASE_T4;
1248 	}
1249 	if (dp->anadv_100fdx) {
1250 		val |= MII_ABILITY_100BASE_TX_FD;
1251 	}
1252 	if (dp->anadv_100hdx) {
1253 		val |= MII_ABILITY_100BASE_TX;
1254 	}
1255 	if (dp->anadv_10fdx) {
1256 		val |= MII_ABILITY_10BASE_T_FD;
1257 	}
1258 	if (dp->anadv_10hdx) {
1259 		val |= MII_ABILITY_10BASE_T;
1260 	}
1261 
1262 	/* set flow control capabilities */
1263 	if (dp->anadv_pause) {
1264 		val |= MII_ABILITY_PAUSE;
1265 	}
1266 	if (dp->anadv_asmpause) {
1267 		val |= MII_ABILITY_ASM_DIR;
1268 	}
1269 
1270 	DPRINTF(0, (CE_CONT,
1271 	    "!%s: %s: setting MII_AN_ADVERT reg:%b, pause:%d, asmpause:%d",
1272 	    dp->name, __func__, val, MII_ABILITY_BITS,
1273 	    dp->anadv_pause, dp->anadv_asmpause));
1274 
1275 	usbgem_mii_write(dp, MII_AN_ADVERT, val, errp);
1276 	if (*errp != USB_SUCCESS) {
1277 		goto usberr;
1278 	}
1279 
1280 	if (dp->mii_status & MII_STATUS_XSTATUS) {
1281 		/*
1282 		 * 1000Base-T GMII support
1283 		 */
1284 		if (!dp->anadv_autoneg) {
1285 			/* enable manual configuration */
1286 			val = MII_1000TC_CFG_EN;
1287 			if (dp->anadv_1000t_ms == 2) {
1288 				val |= MII_1000TC_CFG_VAL;
1289 			}
1290 		} else {
1291 			val = 0;
1292 			if (dp->anadv_1000fdx) {
1293 				val |= MII_1000TC_ADV_FULL;
1294 			}
1295 			if (dp->anadv_1000hdx) {
1296 				val |= MII_1000TC_ADV_HALF;
1297 			}
1298 			switch (dp->anadv_1000t_ms) {
1299 			case 1:
1300 				/* slave */
1301 				val |= MII_1000TC_CFG_EN;
1302 				break;
1303 
1304 			case 2:
1305 				/* master */
1306 				val |= MII_1000TC_CFG_EN | MII_1000TC_CFG_VAL;
1307 				break;
1308 
1309 			default:
1310 				/* auto: do nothing */
1311 				break;
1312 			}
1313 		}
1314 		DPRINTF(0, (CE_CONT,
1315 		    "!%s: %s: setting MII_1000TC reg:%b",
1316 		    dp->name, __func__, val, MII_1000TC_BITS));
1317 
1318 		usbgem_mii_write(dp, MII_1000TC, val, errp);
1319 		if (*errp != USB_SUCCESS) {
1320 			goto usberr;
1321 		}
1322 	}
1323 	return (USB_SUCCESS);
1324 
1325 usberr:
1326 	return (*errp);
1327 }
1328 
1329 static char *usbgem_fc_type[] = {
1330 	"without",
1331 	"with symmetric",
1332 	"with tx",
1333 	"with rx",
1334 };
1335 
1336 #define	USBGEM_LINKUP(dp)	mac_link_update((dp)->mh, LINK_STATE_UP)
1337 #define	USBGEM_LINKDOWN(dp)	mac_link_update((dp)->mh, LINK_STATE_DOWN)
1338 
1339 static uint8_t usbgem_fc_result[4 /* my cap */][4 /* lp cap */] = {
1340 /*	 none	symm	tx	rx/symm */
1341 /* none */
1342 	{FLOW_CONTROL_NONE,
1343 		FLOW_CONTROL_NONE,
1344 			FLOW_CONTROL_NONE,
1345 				FLOW_CONTROL_NONE},
1346 /* sym */
1347 	{FLOW_CONTROL_NONE,
1348 		FLOW_CONTROL_SYMMETRIC,
1349 			FLOW_CONTROL_NONE,
1350 				FLOW_CONTROL_SYMMETRIC},
1351 /* tx */
1352 	{FLOW_CONTROL_NONE,
1353 		FLOW_CONTROL_NONE,
1354 			FLOW_CONTROL_NONE,
1355 				FLOW_CONTROL_TX_PAUSE},
1356 /* rx/symm */
1357 	{FLOW_CONTROL_NONE,
1358 		FLOW_CONTROL_SYMMETRIC,
1359 			FLOW_CONTROL_RX_PAUSE,
1360 				FLOW_CONTROL_SYMMETRIC},
1361 };
1362 
1363 static boolean_t
1364 usbgem_mii_link_check(struct usbgem_dev *dp, int *oldstatep, int *newstatep)
1365 {
1366 	boolean_t	tx_sched = B_FALSE;
1367 	uint16_t	status;
1368 	uint16_t	advert;
1369 	uint16_t	lpable;
1370 	uint16_t	exp;
1371 	uint16_t	ctl1000;
1372 	uint16_t	stat1000;
1373 	uint16_t	val;
1374 	clock_t		now;
1375 	clock_t		diff;
1376 	int		linkdown_action;
1377 	boolean_t	fix_phy = B_FALSE;
1378 	int		err;
1379 	uint_t		rwlock;
1380 
1381 	DPRINTF(4, (CE_CONT, "!%s: %s: time:%d state:%d",
1382 	    dp->name, __func__, ddi_get_lbolt(), dp->mii_state));
1383 
1384 	if (dp->mii_state != MII_STATE_LINKUP) {
1385 		rwlock = RW_WRITER;
1386 	} else {
1387 		rwlock = RW_READER;
1388 	}
1389 again:
1390 	rw_enter(&dp->dev_state_lock, rwlock);
1391 
1392 	/* save old mii state */
1393 	*oldstatep = dp->mii_state;
1394 
1395 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
1396 		/* stop periodic execution of the link watcher */
1397 		dp->mii_interval = 0;
1398 		tx_sched = B_FALSE;
1399 		goto next;
1400 	}
1401 
1402 	now = ddi_get_lbolt();
1403 	diff = now - dp->mii_last_check;
1404 	dp->mii_last_check = now;
1405 
1406 	/*
1407 	 * For NWAM, don't show linkdown state right
1408 	 * when the device is attached.
1409 	 */
1410 	if (dp->linkup_delay > 0) {
1411 		if (dp->linkup_delay > diff) {
1412 			dp->linkup_delay -= diff;
1413 		} else {
1414 			/* link up timeout */
1415 			dp->linkup_delay = -1;
1416 		}
1417 	}
1418 
1419 next_nowait:
1420 	switch (dp->mii_state) {
1421 	case MII_STATE_UNKNOWN:
1422 		goto reset_phy;
1423 
1424 	case MII_STATE_RESETTING:
1425 		dp->mii_timer -= diff;
1426 		if (dp->mii_timer > 0) {
1427 			/* don't read phy registers in resetting */
1428 			dp->mii_interval = WATCH_INTERVAL_FAST;
1429 			goto next;
1430 		}
1431 
1432 		val = usbgem_mii_read(dp, MII_CONTROL, &err);
1433 		if (err != USB_SUCCESS) {
1434 			goto usberr;
1435 		}
1436 		if (val & MII_CONTROL_RESET) {
1437 			cmn_err(CE_NOTE,
1438 			    "!%s: time:%ld resetting phy not complete."
1439 			    " mii_control:0x%b",
1440 			    dp->name, ddi_get_lbolt(),
1441 			    val, MII_CONTROL_BITS);
1442 		}
1443 
1444 		/* ensure neither isolated nor pwrdown nor auto-nego mode */
1445 		usbgem_mii_write(dp, MII_CONTROL, 0, &err);
1446 		if (err != USB_SUCCESS) {
1447 			goto usberr;
1448 		}
1449 #if USBGEM_DEBUG_LEVEL > 10
1450 		val = usbgem_mii_read(dp, MII_CONTROL, &err);
1451 		cmn_err(CE_CONT, "!%s: readback control %b",
1452 		    dp->name, val, MII_CONTROL_BITS);
1453 #endif
1454 		/* As resetting PHY has completed, configure PHY registers */
1455 		if ((*dp->ugc.usbgc_mii_config)(dp, &err) != USB_SUCCESS) {
1456 			/* we failed to configure PHY */
1457 			goto usberr;
1458 		}
1459 
1460 		/* prepare for forced mode */
1461 		usbgem_choose_forcedmode(dp);
1462 
1463 		dp->mii_lpable = 0;
1464 		dp->mii_advert = 0;
1465 		dp->mii_exp = 0;
1466 		dp->mii_ctl1000 = 0;
1467 		dp->mii_stat1000 = 0;
1468 
1469 		dp->flow_control = FLOW_CONTROL_NONE;
1470 
1471 		if (!dp->anadv_autoneg) {
1472 			/* skip auto-negotiation phase */
1473 			dp->mii_state = MII_STATE_MEDIA_SETUP;
1474 			dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout;
1475 			goto next_nowait;
1476 		}
1477 
1478 		/* issue an auto-negotiation command */
1479 		goto autonego;
1480 
1481 	case MII_STATE_AUTONEGOTIATING:
1482 		/*
1483 		 * Autonegotiation in progress
1484 		 */
1485 		dp->mii_timer -= diff;
1486 		if (dp->mii_timer -
1487 		    (dp->ugc.usbgc_mii_an_timeout - dp->ugc.usbgc_mii_an_wait)
1488 		    > 0) {
1489 			/* wait for minimum time (2.3 - 2.5 sec) */
1490 			dp->mii_interval = WATCH_INTERVAL_FAST;
1491 			goto next;
1492 		}
1493 
1494 		/* read PHY status */
1495 		status = usbgem_mii_read(dp, MII_STATUS, &err);
1496 		if (err != USB_SUCCESS) {
1497 			goto usberr;
1498 		}
1499 		DPRINTF(4, (CE_CONT,
1500 		    "!%s: %s: called: mii_state:%d MII_STATUS reg:%b",
1501 		    dp->name, __func__, dp->mii_state,
1502 		    status, MII_STATUS_BITS));
1503 
1504 		if (status & MII_STATUS_REMFAULT) {
1505 			/*
1506 			 * The link parnert told me something wrong happend.
1507 			 * What do we do ?
1508 			 */
1509 			cmn_err(CE_CONT,
1510 			    "!%s: auto-negotiation failed: remote fault",
1511 			    dp->name);
1512 			goto autonego;
1513 		}
1514 
1515 		if ((status & MII_STATUS_ANDONE) == 0) {
1516 			if (dp->mii_timer <= 0) {
1517 				/*
1518 				 * Auto-negotiation has been timed out,
1519 				 * Reset PHY and try again.
1520 				 */
1521 				if (!dp->mii_supress_msg) {
1522 					cmn_err(CE_WARN,
1523 					    "!%s: auto-negotiation failed:"
1524 					    " timeout",
1525 					    dp->name);
1526 					dp->mii_supress_msg = B_TRUE;
1527 				}
1528 				goto autonego;
1529 			}
1530 			/*
1531 			 * Auto-negotiation is in progress. Wait for a while.
1532 			 */
1533 			dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval;
1534 			goto next;
1535 		}
1536 
1537 		/*
1538 		 * Auto-negotiation has been completed. Let's go to AN_DONE.
1539 		 */
1540 		dp->mii_state = MII_STATE_AN_DONE;
1541 		dp->mii_supress_msg = B_FALSE;
1542 		DPRINTF(0, (CE_CONT,
1543 		    "!%s: auto-negotiation completed, MII_STATUS:%b",
1544 		    dp->name, status, MII_STATUS_BITS));
1545 
1546 		if (dp->ugc.usbgc_mii_an_delay > 0) {
1547 			dp->mii_timer = dp->ugc.usbgc_mii_an_delay;
1548 			dp->mii_interval = drv_usectohz(20*1000);
1549 			goto next;
1550 		}
1551 
1552 		dp->mii_timer = 0;
1553 		diff = 0;
1554 		goto next_nowait;
1555 
1556 	case MII_STATE_AN_DONE:
1557 		/*
1558 		 * Auto-negotiation has done. Now we can set up media.
1559 		 */
1560 		dp->mii_timer -= diff;
1561 		if (dp->mii_timer > 0) {
1562 			/* wait for a while */
1563 			dp->mii_interval = WATCH_INTERVAL_FAST;
1564 			goto next;
1565 		}
1566 
1567 		/*
1568 		 * Setup speed and duplex mode according with
1569 		 * the result of auto negotiation.
1570 		 */
1571 
1572 		/*
1573 		 * Read registers required to determin current
1574 		 * duplex mode and media speed.
1575 		 */
1576 		if (dp->ugc.usbgc_mii_an_delay > 0) {
1577 			/* the 'status' variable is not initialized yet */
1578 			status = usbgem_mii_read(dp, MII_STATUS, &err);
1579 			if (err != USB_SUCCESS) {
1580 				goto usberr;
1581 			}
1582 		}
1583 		advert = usbgem_mii_read(dp, MII_AN_ADVERT, &err);
1584 		if (err != USB_SUCCESS) {
1585 			goto usberr;
1586 		}
1587 		lpable = usbgem_mii_read(dp, MII_AN_LPABLE, &err);
1588 		if (err != USB_SUCCESS) {
1589 			goto usberr;
1590 		}
1591 		exp = usbgem_mii_read(dp, MII_AN_EXPANSION, &err);
1592 		if (err != USB_SUCCESS) {
1593 			goto usberr;
1594 		}
1595 		if (exp == 0xffff) {
1596 			/* some phys don't have exp register */
1597 			exp = 0;
1598 		}
1599 
1600 		ctl1000 = 0;
1601 		stat1000 = 0;
1602 		if (dp->mii_status & MII_STATUS_XSTATUS) {
1603 			ctl1000 = usbgem_mii_read(dp, MII_1000TC, &err);
1604 			if (err != USB_SUCCESS) {
1605 				goto usberr;
1606 			}
1607 			stat1000 = usbgem_mii_read(dp, MII_1000TS, &err);
1608 			if (err != USB_SUCCESS) {
1609 				goto usberr;
1610 			}
1611 		}
1612 		dp->mii_lpable = lpable;
1613 		dp->mii_advert = advert;
1614 		dp->mii_exp = exp;
1615 		dp->mii_ctl1000 = ctl1000;
1616 		dp->mii_stat1000 = stat1000;
1617 
1618 		cmn_err(CE_CONT,
1619 		    "!%s: auto-negotiation done: "
1620 		    "status:%b, advert:%b, lpable:%b, exp:%b",
1621 		    dp->name,
1622 		    status, MII_STATUS_BITS,
1623 		    advert, MII_ABILITY_BITS,
1624 		    lpable, MII_ABILITY_BITS,
1625 		    exp, MII_AN_EXP_BITS);
1626 
1627 		DPRINTF(0, (CE_CONT, "!%s: MII_STATUS:%b",
1628 		    dp->name, status, MII_STATUS_BITS));
1629 
1630 		if (dp->mii_status & MII_STATUS_XSTATUS) {
1631 			cmn_err(CE_CONT,
1632 			    "! MII_1000TC reg:%b, MII_1000TS reg:%b",
1633 			    ctl1000, MII_1000TC_BITS,
1634 			    stat1000, MII_1000TS_BITS);
1635 		}
1636 
1637 		if (usbgem_population(lpable) <= 1 &&
1638 		    (exp & MII_AN_EXP_LPCANAN) == 0) {
1639 			if ((advert & MII_ABILITY_TECH) != lpable) {
1640 				cmn_err(CE_WARN,
1641 				    "!%s: but the link partner doesn't seem"
1642 				    " to have auto-negotiation capability."
1643 				    " please check the link configuration.",
1644 				    dp->name);
1645 			}
1646 			/*
1647 			 * it should be a result of pararell detection,
1648 			 * which cannot detect duplex mode.
1649 			 */
1650 			if ((advert & lpable) == 0 &&
1651 			    lpable & MII_ABILITY_10BASE_T) {
1652 				/* no common technology, try 10M half mode */
1653 				lpable |= advert & MII_ABILITY_10BASE_T;
1654 				fix_phy = B_TRUE;
1655 			}
1656 		} else if (lpable == 0) {
1657 			cmn_err(CE_WARN, "!%s: wrong lpable.", dp->name);
1658 			goto reset_phy;
1659 		}
1660 		/*
1661 		 * configure current link mode according to AN priority.
1662 		 */
1663 		val = advert & lpable;
1664 		if ((ctl1000 & MII_1000TC_ADV_FULL) &&
1665 		    (stat1000 & MII_1000TS_LP_FULL)) {
1666 			/* 1000BaseT & full duplex */
1667 			dp->speed = USBGEM_SPD_1000;
1668 			dp->full_duplex = B_TRUE;
1669 		} else if ((ctl1000 & MII_1000TC_ADV_HALF) &&
1670 		    (stat1000 & MII_1000TS_LP_HALF)) {
1671 			/* 1000BaseT & half duplex */
1672 			dp->speed = USBGEM_SPD_1000;
1673 			dp->full_duplex = B_FALSE;
1674 		} else if ((val & MII_ABILITY_100BASE_TX_FD)) {
1675 			/* 100BaseTx & fullduplex */
1676 			dp->speed = USBGEM_SPD_100;
1677 			dp->full_duplex = B_TRUE;
1678 		} else if ((val & MII_ABILITY_100BASE_T4)) {
1679 			/* 100BaseTx & fullduplex */
1680 			dp->speed = USBGEM_SPD_100;
1681 			dp->full_duplex = B_TRUE;
1682 		} else if ((val & MII_ABILITY_100BASE_TX)) {
1683 			/* 100BaseTx & half duplex */
1684 			dp->speed = USBGEM_SPD_100;
1685 			dp->full_duplex = B_FALSE;
1686 		} else if ((val & MII_ABILITY_10BASE_T_FD)) {
1687 			/* 10BaseT & full duplex */
1688 			dp->speed = USBGEM_SPD_10;
1689 			dp->full_duplex = B_TRUE;
1690 		} else if ((val & MII_ABILITY_10BASE_T)) {
1691 			/* 10BaseT & half duplex */
1692 			dp->speed = USBGEM_SPD_10;
1693 			dp->full_duplex = B_FALSE;
1694 		} else {
1695 			/*
1696 			 * the link partner doesn't seem to have
1697 			 * auto-negotiation capability and our PHY
1698 			 * could not report current mode correctly.
1699 			 * We guess current mode by mii_control register.
1700 			 */
1701 			val = usbgem_mii_read(dp, MII_CONTROL, &err);
1702 			if (err != USB_SUCCESS) {
1703 				goto usberr;
1704 			}
1705 
1706 			/* select 100m half or 10m half */
1707 			dp->speed = (val & MII_CONTROL_100MB) ?
1708 			    USBGEM_SPD_100 : USBGEM_SPD_10;
1709 			dp->full_duplex = B_FALSE;
1710 			fix_phy = B_TRUE;
1711 
1712 			cmn_err(CE_NOTE,
1713 			    "!%s: auto-negotiation done but "
1714 			    "common ability not found.\n"
1715 			    "PHY state: control:%b advert:%b lpable:%b\n"
1716 			    "guessing %d Mbps %s duplex mode",
1717 			    dp->name,
1718 			    val, MII_CONTROL_BITS,
1719 			    advert, MII_ABILITY_BITS,
1720 			    lpable, MII_ABILITY_BITS,
1721 			    usbgem_speed_value[dp->speed],
1722 			    dp->full_duplex ? "full" : "half");
1723 		}
1724 
1725 		if (dp->full_duplex) {
1726 			dp->flow_control =
1727 			    usbgem_fc_result[fc_cap_decode(advert)]
1728 			    [fc_cap_decode(lpable)];
1729 		} else {
1730 			dp->flow_control = FLOW_CONTROL_NONE;
1731 		}
1732 		dp->mii_state = MII_STATE_MEDIA_SETUP;
1733 		dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout;
1734 		goto next_nowait;
1735 
1736 	case MII_STATE_MEDIA_SETUP:
1737 		DPRINTF(2, (CE_CONT, "!%s: setup midia mode", dp->name));
1738 
1739 		/* assume the link state is down */
1740 		dp->mii_state = MII_STATE_LINKDOWN;
1741 		dp->mii_supress_msg = B_FALSE;
1742 
1743 		/* use short interval */
1744 		dp->mii_interval = WATCH_INTERVAL_FAST;
1745 
1746 		if ((!dp->anadv_autoneg) ||
1747 		    dp->ugc.usbgc_mii_an_oneshot || fix_phy) {
1748 
1749 			/*
1750 			 * write the result of auto negotiation back.
1751 			 */
1752 			val = usbgem_mii_read(dp, MII_CONTROL, &err);
1753 			if (err != USB_SUCCESS) {
1754 				goto usberr;
1755 			}
1756 			val &= ~(MII_CONTROL_SPEED | MII_CONTROL_FDUPLEX |
1757 			    MII_CONTROL_ANE   | MII_CONTROL_RSAN);
1758 
1759 			if (dp->full_duplex) {
1760 				val |= MII_CONTROL_FDUPLEX;
1761 			}
1762 
1763 			switch (dp->speed) {
1764 			case USBGEM_SPD_1000:
1765 				val |= MII_CONTROL_1000MB;
1766 				break;
1767 
1768 			case USBGEM_SPD_100:
1769 				val |= MII_CONTROL_100MB;
1770 				break;
1771 
1772 			default:
1773 				cmn_err(CE_WARN, "%s: unknown speed:%d",
1774 				    dp->name, dp->speed);
1775 				/* FALLTHROUGH */
1776 
1777 			case USBGEM_SPD_10:
1778 				/* for USBGEM_SPD_10, do nothing */
1779 				break;
1780 			}
1781 
1782 			if (dp->mii_status & MII_STATUS_XSTATUS) {
1783 				usbgem_mii_write(dp,
1784 				    MII_1000TC, MII_1000TC_CFG_EN, &err);
1785 				if (err != USB_SUCCESS) {
1786 					goto usberr;
1787 				}
1788 			}
1789 			usbgem_mii_write(dp, MII_CONTROL, val, &err);
1790 			if (err != USB_SUCCESS) {
1791 				goto usberr;
1792 			}
1793 		}
1794 		/*
1795 		 * XXX -- nic state should be one of
1796 		 * NIC_STATE_DISCONNECTED
1797 		 * NIC_STATE_STOPPED
1798 		 * NIC_STATE_INITIALIZED
1799 		 * NIC_STATE_ONLINE
1800 		 */
1801 		if (dp->nic_state >= NIC_STATE_INITIALIZED) {
1802 			/* notify the result of autonegotiation to mac */
1803 			if (usbgem_hal_set_media(dp) != USB_SUCCESS) {
1804 				goto usberr;
1805 			}
1806 		}
1807 		goto next_nowait;
1808 
1809 	case MII_STATE_LINKDOWN:
1810 		status = usbgem_mii_read(dp, MII_STATUS, &err);
1811 		if (err != USB_SUCCESS) {
1812 			goto usberr;
1813 		}
1814 		if (status & MII_STATUS_LINKUP) {
1815 			/*
1816 			 * Link is going up
1817 			 */
1818 			dp->mii_state = MII_STATE_LINKUP;
1819 			dp->mii_supress_msg = B_FALSE;
1820 
1821 			DPRINTF(0, (CE_CONT,
1822 			    "!%s: link up detected: status:%b",
1823 			    dp->name, status, MII_STATUS_BITS));
1824 
1825 			/*
1826 			 * MII_CONTROL_100MB and  MII_CONTROL_FDUPLEX are
1827 			 * ignored when MII_CONTROL_ANE is set.
1828 			 */
1829 			cmn_err(CE_CONT,
1830 			    "!%s: Link up: %d Mbps %s duplex %s flow control",
1831 			    dp->name,
1832 			    usbgem_speed_value[dp->speed],
1833 			    dp->full_duplex ? "full" : "half",
1834 			    usbgem_fc_type[dp->flow_control]);
1835 
1836 			dp->mii_interval =
1837 			    dp->ugc.usbgc_mii_link_watch_interval;
1838 
1839 			if (dp->ugc.usbgc_mii_hw_link_detection &&
1840 			    dp->nic_state == NIC_STATE_ONLINE) {
1841 				dp->mii_interval = 0;
1842 			}
1843 
1844 			if (dp->nic_state == NIC_STATE_ONLINE) {
1845 				if (dp->mac_state == MAC_STATE_INITIALIZED) {
1846 					(void) usbgem_mac_start(dp);
1847 				}
1848 				tx_sched = B_TRUE;
1849 			}
1850 
1851 			goto next;
1852 		}
1853 
1854 		dp->mii_supress_msg = B_TRUE;
1855 		if (dp->anadv_autoneg) {
1856 			dp->mii_timer -= diff;
1857 			if (dp->mii_timer <= 0) {
1858 				/*
1859 				 * the link down timer expired.
1860 				 * need to restart auto-negotiation.
1861 				 */
1862 				linkdown_action =
1863 				    dp->ugc.usbgc_mii_linkdown_timeout_action;
1864 				goto restart_autonego;
1865 			}
1866 		}
1867 		/* don't change mii_state */
1868 		goto next;
1869 
1870 	case MII_STATE_LINKUP:
1871 		if (rwlock == RW_READER) {
1872 			/* first pass, read mii status */
1873 			status = usbgem_mii_read(dp, MII_STATUS, &err);
1874 			if (err != USB_SUCCESS) {
1875 				goto usberr;
1876 			}
1877 		}
1878 		if ((status & MII_STATUS_LINKUP) == 0) {
1879 			/*
1880 			 * Link is going down
1881 			 */
1882 			cmn_err(CE_NOTE,
1883 			    "!%s: link down detected: status:%b",
1884 			    dp->name, status, MII_STATUS_BITS);
1885 			/*
1886 			 * Acquire exclusive lock to change mii_state
1887 			 */
1888 			if (rwlock == RW_READER) {
1889 				rwlock = RW_WRITER;
1890 				rw_exit(&dp->dev_state_lock);
1891 				goto again;
1892 			}
1893 
1894 			dp->mii_state = MII_STATE_LINKDOWN;
1895 			dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout;
1896 
1897 			/*
1898 			 * As we may change the state of the device,
1899 			 * let us acquire exclusive lock for the state.
1900 			 */
1901 			if (dp->nic_state == NIC_STATE_ONLINE &&
1902 			    dp->mac_state == MAC_STATE_ONLINE &&
1903 			    dp->ugc.usbgc_mii_stop_mac_on_linkdown) {
1904 				(void) usbgem_restart_nic(dp);
1905 				/* drain tx */
1906 				tx_sched = B_TRUE;
1907 			}
1908 
1909 			if (dp->anadv_autoneg) {
1910 				/* need to restart auto-negotiation */
1911 				linkdown_action =
1912 				    dp->ugc.usbgc_mii_linkdown_action;
1913 				goto restart_autonego;
1914 			}
1915 			/*
1916 			 * don't use hw link down detection until the link
1917 			 * status become stable for a while.
1918 			 */
1919 			dp->mii_interval =
1920 			    dp->ugc.usbgc_mii_link_watch_interval;
1921 
1922 			goto next;
1923 		}
1924 
1925 		/*
1926 		 * still link up, no need to change mii_state
1927 		 */
1928 		if (dp->ugc.usbgc_mii_hw_link_detection &&
1929 		    dp->nic_state == NIC_STATE_ONLINE) {
1930 			/*
1931 			 * no need to check link status periodicly
1932 			 * if nic can generate interrupts when link go down.
1933 			 */
1934 			dp->mii_interval = 0;
1935 		}
1936 		goto next;
1937 	}
1938 	/* NOTREACHED */
1939 	cmn_err(CE_PANIC, "!%s: %s: not reached", dp->name, __func__);
1940 
1941 	/*
1942 	 * Actions for new state.
1943 	 */
1944 restart_autonego:
1945 	switch (linkdown_action) {
1946 	case MII_ACTION_RESET:
1947 		if (!dp->mii_supress_msg) {
1948 			cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
1949 		}
1950 		dp->mii_supress_msg = B_TRUE;
1951 		goto reset_phy;
1952 
1953 	case MII_ACTION_NONE:
1954 		dp->mii_supress_msg = B_TRUE;
1955 		if (dp->ugc.usbgc_mii_an_oneshot) {
1956 			goto autonego;
1957 		}
1958 		/* PHY will restart autonego automatically */
1959 		dp->mii_state = MII_STATE_AUTONEGOTIATING;
1960 		dp->mii_timer = dp->ugc.usbgc_mii_an_timeout;
1961 		dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval;
1962 		goto next;
1963 
1964 	case MII_ACTION_RSA:
1965 		if (!dp->mii_supress_msg) {
1966 			cmn_err(CE_CONT, "!%s: restarting auto-negotiation",
1967 			    dp->name);
1968 		}
1969 		dp->mii_supress_msg = B_TRUE;
1970 		goto autonego;
1971 
1972 	default:
1973 		cmn_err(CE_PANIC, "!%s: unknowm linkdown action: %d",
1974 		    dp->name, dp->ugc.usbgc_mii_linkdown_action);
1975 	}
1976 	/* NOTREACHED */
1977 
1978 reset_phy:
1979 	if (!dp->mii_supress_msg) {
1980 		cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
1981 	}
1982 	dp->mii_state = MII_STATE_RESETTING;
1983 	dp->mii_timer = dp->ugc.usbgc_mii_reset_timeout;
1984 	if (!dp->ugc.usbgc_mii_dont_reset) {
1985 		usbgem_mii_write(dp, MII_CONTROL, MII_CONTROL_RESET, &err);
1986 		if (err != USB_SUCCESS) {
1987 			goto usberr;
1988 		}
1989 	}
1990 	dp->mii_interval = WATCH_INTERVAL_FAST;
1991 	goto next;
1992 
1993 autonego:
1994 	if (!dp->mii_supress_msg) {
1995 		cmn_err(CE_CONT, "!%s: auto-negotiation started", dp->name);
1996 	}
1997 	dp->mii_state = MII_STATE_AUTONEGOTIATING;
1998 	dp->mii_timer = dp->ugc.usbgc_mii_an_timeout;
1999 
2000 	/* start/restart autoneg */
2001 	val = usbgem_mii_read(dp, MII_CONTROL, &err) &
2002 	    ~(MII_CONTROL_ISOLATE | MII_CONTROL_PWRDN | MII_CONTROL_RESET);
2003 	if (err != USB_SUCCESS) {
2004 		goto usberr;
2005 	}
2006 	if (val & MII_CONTROL_ANE) {
2007 		val |= MII_CONTROL_RSAN;
2008 	}
2009 	usbgem_mii_write(dp, MII_CONTROL,
2010 	    val | dp->ugc.usbgc_mii_an_cmd | MII_CONTROL_ANE, &err);
2011 	if (err != USB_SUCCESS) {
2012 		goto usberr;
2013 	}
2014 
2015 	dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval;
2016 	goto next;
2017 
2018 usberr:
2019 	dp->mii_state = MII_STATE_UNKNOWN;
2020 	dp->mii_interval = dp->ugc.usbgc_mii_link_watch_interval;
2021 	tx_sched = B_TRUE;
2022 
2023 next:
2024 	*newstatep = dp->mii_state;
2025 	rw_exit(&dp->dev_state_lock);
2026 	return (tx_sched);
2027 }
2028 
2029 static void
2030 usbgem_mii_link_watcher(struct usbgem_dev *dp)
2031 {
2032 	int		old_mii_state;
2033 	int		new_mii_state;
2034 	boolean_t	tx_sched;
2035 
2036 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2037 
2038 	for (; ; ) {
2039 
2040 		mutex_enter(&dp->link_watcher_lock);
2041 		if (dp->mii_interval) {
2042 			(void) cv_timedwait(&dp->link_watcher_wait_cv,
2043 			    &dp->link_watcher_lock,
2044 			    dp->mii_interval + ddi_get_lbolt());
2045 		} else {
2046 			cv_wait(&dp->link_watcher_wait_cv,
2047 			    &dp->link_watcher_lock);
2048 		}
2049 		mutex_exit(&dp->link_watcher_lock);
2050 
2051 		if (dp->link_watcher_stop) {
2052 			break;
2053 		}
2054 
2055 		/* we block callbacks from disconnect/suspend and restart */
2056 		tx_sched = usbgem_mii_link_check(dp,
2057 		    &old_mii_state, &new_mii_state);
2058 
2059 		/*
2060 		 * gld v2 notifier functions are not able to
2061 		 * be called with any locks in this layer.
2062 		 */
2063 		if (tx_sched) {
2064 			/* kick potentially stopped downstream */
2065 			mac_tx_update(dp->mh);
2066 		}
2067 
2068 		if (old_mii_state != new_mii_state) {
2069 			/* notify new mii link state */
2070 			if (new_mii_state == MII_STATE_LINKUP) {
2071 				dp->linkup_delay = 0;
2072 				USBGEM_LINKUP(dp);
2073 			} else if (dp->linkup_delay <= 0) {
2074 				USBGEM_LINKDOWN(dp);
2075 			}
2076 		} else if (dp->linkup_delay < 0) {
2077 			/* first linkup timeout */
2078 			dp->linkup_delay = 0;
2079 			USBGEM_LINKDOWN(dp);
2080 		}
2081 	}
2082 
2083 	thread_exit();
2084 }
2085 
2086 void
2087 usbgem_mii_update_link(struct usbgem_dev *dp)
2088 {
2089 	cv_signal(&dp->link_watcher_wait_cv);
2090 }
2091 
2092 int
2093 usbgem_mii_probe_default(struct usbgem_dev *dp)
2094 {
2095 	int		phy;
2096 	uint16_t	status;
2097 	uint16_t	xstatus;
2098 	int		err;
2099 	uint16_t	adv;
2100 	uint16_t	adv_org;
2101 
2102 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2103 
2104 	/*
2105 	 * Scan PHY
2106 	 */
2107 	dp->mii_status = 0;
2108 
2109 	/* Try default phy first */
2110 	if (dp->mii_phy_addr) {
2111 		status = usbgem_mii_read(dp, MII_STATUS, &err);
2112 		if (err != USB_SUCCESS) {
2113 			goto usberr;
2114 		}
2115 		if (status != 0xffff && status != 0x0000) {
2116 			goto PHY_found;
2117 		}
2118 
2119 		if (dp->mii_phy_addr < 0) {
2120 			cmn_err(CE_NOTE,
2121 		    "!%s: failed to probe default internal and/or non-MII PHY",
2122 			    dp->name);
2123 			return (USB_FAILURE);
2124 		}
2125 
2126 		cmn_err(CE_NOTE,
2127 		    "!%s: failed to probe default MII PHY at %d",
2128 		    dp->name, dp->mii_phy_addr);
2129 	}
2130 
2131 	/* Try all possible address */
2132 	for (phy = dp->ugc.usbgc_mii_addr_min; phy < 32; phy++) {
2133 		dp->mii_phy_addr = phy;
2134 		status = usbgem_mii_read(dp, MII_STATUS, &err);
2135 		if (err != USB_SUCCESS) {
2136 			DPRINTF(0, (CE_CONT,
2137 			    "!%s: %s: mii_read(status) failed",
2138 			    dp->name, __func__));
2139 			goto usberr;
2140 		}
2141 
2142 		if (status != 0xffff && status != 0x0000) {
2143 			usbgem_mii_write(dp, MII_CONTROL, 0, &err);
2144 			if (err != USB_SUCCESS) {
2145 				DPRINTF(0, (CE_CONT,
2146 				    "!%s: %s: mii_write(control) failed",
2147 				    dp->name, __func__));
2148 				goto usberr;
2149 			}
2150 			goto PHY_found;
2151 		}
2152 	}
2153 	for (phy = dp->ugc.usbgc_mii_addr_min; phy < 32; phy++) {
2154 		dp->mii_phy_addr = phy;
2155 		usbgem_mii_write(dp, MII_CONTROL, 0, &err);
2156 		if (err != USB_SUCCESS) {
2157 			DPRINTF(0, (CE_CONT,
2158 			    "!%s: %s: mii_write(control) failed",
2159 			    dp->name, __func__));
2160 			goto usberr;
2161 		}
2162 		status = usbgem_mii_read(dp, MII_STATUS, &err);
2163 		if (err != USB_SUCCESS) {
2164 			DPRINTF(0, (CE_CONT,
2165 			    "!%s: %s: mii_read(status) failed",
2166 			    dp->name, __func__));
2167 			goto usberr;
2168 		}
2169 
2170 		if (status != 0xffff && status != 0) {
2171 			goto PHY_found;
2172 		}
2173 	}
2174 
2175 	cmn_err(CE_NOTE, "!%s: no MII PHY found", dp->name);
2176 	return (USB_FAILURE);
2177 
2178 PHY_found:
2179 	dp->mii_status = status;
2180 	dp->mii_status_ro = ~status;
2181 	dp->mii_phy_id = usbgem_mii_read(dp, MII_PHYIDH, &err) << 16;
2182 	if (err != USB_SUCCESS) {
2183 		DPRINTF(0, (CE_CONT,
2184 		    "!%s: %s: mii_read(PHYIDH) failed",
2185 		    dp->name, __func__));
2186 		goto usberr;
2187 	}
2188 	dp->mii_phy_id |= usbgem_mii_read(dp, MII_PHYIDL, &err);
2189 	if (err != USB_SUCCESS) {
2190 		DPRINTF(0, (CE_CONT,
2191 		    "!%s: %s: mii_read(PHYIDL) failed",
2192 		    dp->name, __func__));
2193 		goto usberr;
2194 	}
2195 
2196 	if (dp->mii_phy_addr < 0) {
2197 		cmn_err(CE_CONT, "!%s: using internal/non-MII PHY(0x%08x)",
2198 		    dp->name, dp->mii_phy_id);
2199 	} else {
2200 		cmn_err(CE_CONT, "!%s: MII PHY (0x%08x) found at %d",
2201 		    dp->name, dp->mii_phy_id, dp->mii_phy_addr);
2202 	}
2203 
2204 	cmn_err(CE_CONT,
2205 	    "!%s: PHY control:%b, status:%b, advert:%b, lpar:%b, exp:%b",
2206 	    dp->name,
2207 	    usbgem_mii_read(dp, MII_CONTROL, &err), MII_CONTROL_BITS,
2208 	    status, MII_STATUS_BITS,
2209 	    usbgem_mii_read(dp, MII_AN_ADVERT, &err), MII_ABILITY_BITS,
2210 	    usbgem_mii_read(dp, MII_AN_LPABLE, &err), MII_ABILITY_BITS,
2211 	    usbgem_mii_read(dp, MII_AN_EXPANSION, &err), MII_AN_EXP_BITS);
2212 
2213 	dp->mii_xstatus = 0;
2214 	if (status & MII_STATUS_XSTATUS) {
2215 		dp->mii_xstatus = usbgem_mii_read(dp, MII_XSTATUS, &err);
2216 
2217 		cmn_err(CE_CONT, "!%s: xstatus:%b",
2218 		    dp->name, dp->mii_xstatus, MII_XSTATUS_BITS);
2219 	}
2220 	dp->mii_xstatus_ro = ~dp->mii_xstatus;
2221 
2222 	/* check if the phy can advertize pause abilities */
2223 	adv_org = usbgem_mii_read(dp, MII_AN_ADVERT, &err);
2224 	if (err != USB_SUCCESS) {
2225 		goto usberr;
2226 	}
2227 
2228 	usbgem_mii_write(dp, MII_AN_ADVERT,
2229 	    MII_ABILITY_PAUSE | MII_ABILITY_ASM_DIR, &err);
2230 	if (err != USB_SUCCESS) {
2231 		goto usberr;
2232 	}
2233 
2234 	adv = usbgem_mii_read(dp, MII_AN_ADVERT, &err);
2235 	if (err != USB_SUCCESS) {
2236 		goto usberr;
2237 	}
2238 
2239 	if ((adv & MII_ABILITY_PAUSE) == 0) {
2240 		dp->ugc.usbgc_flow_control &= ~1;
2241 	}
2242 
2243 	if ((adv & MII_ABILITY_ASM_DIR) == 0) {
2244 		dp->ugc.usbgc_flow_control &= ~2;
2245 	}
2246 
2247 	usbgem_mii_write(dp, MII_AN_ADVERT, adv_org, &err);
2248 	if (err != USB_SUCCESS) {
2249 		goto usberr;
2250 	}
2251 	return (USB_SUCCESS);
2252 
2253 usberr:
2254 	return (USB_FAILURE);
2255 }
2256 
2257 int
2258 usbgem_mii_init_default(struct usbgem_dev *dp)
2259 {
2260 	/* ENPTY */
2261 	return (USB_SUCCESS);
2262 }
2263 
2264 static int
2265 usbgem_mii_start(struct usbgem_dev *dp)
2266 {
2267 	int	err;
2268 	kthread_t	*lwth;
2269 
2270 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2271 
2272 	/* make a first call of usbgem_mii_link_check() */
2273 	dp->link_watcher_stop = 0;
2274 	dp->mii_state = MII_STATE_UNKNOWN;
2275 	dp->mii_interval = drv_usectohz(1000*1000); /* 1sec */
2276 	dp->mii_last_check = ddi_get_lbolt();
2277 	dp->linkup_delay = 600 * drv_usectohz(1000*1000); /* 10 minutes */
2278 
2279 	lwth = thread_create(NULL, 0, usbgem_mii_link_watcher, dp, 0, &p0,
2280 	    TS_RUN, minclsyspri);
2281 	if (lwth == NULL) {
2282 		cmn_err(CE_WARN,
2283 		    "!%s: %s: failed to create a link watcher thread",
2284 		    dp->name, __func__);
2285 		return (USB_FAILURE);
2286 	}
2287 	dp->link_watcher_did = lwth->t_did;
2288 
2289 	return (USB_SUCCESS);
2290 }
2291 
2292 static void
2293 usbgem_mii_stop(struct usbgem_dev *dp)
2294 {
2295 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2296 
2297 	/* Ensure timer routine stopped */
2298 	dp->link_watcher_stop = 1;
2299 	cv_signal(&dp->link_watcher_wait_cv);
2300 	thread_join(dp->link_watcher_did);
2301 }
2302 
2303 /* ============================================================== */
2304 /*
2305  * internal mac register operation interface
2306  */
2307 /* ============================================================== */
2308 /*
2309  * usbgem_mac_init: cold start
2310  */
2311 static int
2312 usbgem_mac_init(struct usbgem_dev *dp)
2313 {
2314 	int	err;
2315 
2316 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2317 
2318 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
2319 		/* pretend we succeeded */
2320 		return (USB_SUCCESS);
2321 	}
2322 
2323 	ASSERT(dp->mac_state == MAC_STATE_STOPPED);
2324 
2325 	/* reset fatal error timestamp */
2326 	dp->fatal_error = (clock_t)0;
2327 
2328 	/* reset tx side state */
2329 	mutex_enter(&dp->txlock);
2330 	dp->tx_busy_cnt = 0;
2331 	dp->tx_max_packets = dp->ugc.usbgc_tx_list_max;
2332 	mutex_exit(&dp->txlock);
2333 
2334 	/* reset rx side state */
2335 	mutex_enter(&dp->rxlock);
2336 	dp->rx_busy_cnt = 0;
2337 	mutex_exit(&dp->rxlock);
2338 
2339 	err = usbgem_hal_init_chip(dp);
2340 	if (err == USB_SUCCESS) {
2341 		dp->mac_state = MAC_STATE_INITIALIZED;
2342 	}
2343 
2344 	return (err);
2345 }
2346 
2347 /*
2348  * usbgem_mac_start: warm start
2349  */
2350 static int
2351 usbgem_mac_start(struct usbgem_dev *dp)
2352 {
2353 	int	err;
2354 	int	i;
2355 	usb_flags_t	flags = 0;
2356 	usb_intr_req_t	*req;
2357 #ifdef USBGEM_DEBUG_LEVEL
2358 	usb_pipe_state_t	p_state;
2359 #endif
2360 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2361 
2362 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
2363 		/* do nothing but don't return failure */
2364 		return (USB_SUCCESS);
2365 	}
2366 
2367 	if (dp->mac_state != MAC_STATE_INITIALIZED) {
2368 		/* don't return failer */
2369 		DPRINTF(0, (CE_CONT,
2370 		    "!%s: %s: mac_state(%d) is not MAC_STATE_INITIALIZED",
2371 		    dp->name, __func__, dp->mac_state));
2372 		goto x;
2373 	}
2374 
2375 	dp->mac_state = MAC_STATE_ONLINE;
2376 
2377 	if (usbgem_hal_start_chip(dp) != USB_SUCCESS) {
2378 		cmn_err(CE_NOTE,
2379 		    "!%s: %s: usb error was detected during start_chip",
2380 		    dp->name, __func__);
2381 		goto x;
2382 	}
2383 
2384 #ifdef USBGEM_DEBUG_LEVEL
2385 	usb_pipe_get_state(dp->intr_pipe, &p_state, 0);
2386 	ASSERT(p_state == USB_PIPE_STATE_IDLE);
2387 #endif /* USBGEM_DEBUG_LEVEL */
2388 
2389 	if (dp->ugc.usbgc_interrupt && dp->intr_pipe) {
2390 
2391 		/* make a request for interrupt */
2392 
2393 		req = usb_alloc_intr_req(dp->dip, 0, USB_FLAGS_SLEEP);
2394 		if (req == NULL) {
2395 			cmn_err(CE_WARN, "!%s: %s: failed to allocate intreq",
2396 			    dp->name, __func__);
2397 			goto x;
2398 		}
2399 		req->intr_data = NULL;
2400 		req->intr_client_private = (usb_opaque_t)dp;
2401 		req->intr_timeout = 0;
2402 		req->intr_attributes =
2403 		    USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
2404 		req->intr_len = dp->ep_intr->wMaxPacketSize;
2405 		req->intr_cb = usbgem_intr_cb;
2406 		req->intr_exc_cb = usbgem_intr_cb;
2407 		req->intr_completion_reason = 0;
2408 		req->intr_cb_flags = 0;
2409 
2410 		err = usb_pipe_intr_xfer(dp->intr_pipe, req, flags);
2411 		if (err != USB_SUCCESS) {
2412 			cmn_err(CE_WARN,
2413 			    "%s: err:%d failed to start polling of intr pipe",
2414 			    dp->name, err);
2415 			goto x;
2416 		}
2417 	}
2418 
2419 	/* kick to receive the first packet */
2420 	if (usbgem_init_rx_buf(dp) != USB_SUCCESS) {
2421 		goto err_stop_intr;
2422 	}
2423 	dp->rx_active = B_TRUE;
2424 
2425 	return (USB_SUCCESS);
2426 
2427 err_stop_intr:
2428 	/* stop the interrupt pipe */
2429 	DPRINTF(0, (CE_CONT, "!%s: %s: FAULURE", dp->name, __func__));
2430 	if (dp->ugc.usbgc_interrupt && dp->intr_pipe) {
2431 		usb_pipe_stop_intr_polling(dp->intr_pipe, USB_FLAGS_SLEEP);
2432 	}
2433 x:
2434 	ASSERT(dp->mac_state == MAC_STATE_ONLINE);
2435 	/* we use another flag to indicate error state. */
2436 	if (dp->fatal_error == (clock_t)0) {
2437 		dp->fatal_error = usbgem_timestamp_nz();
2438 	}
2439 	return (USB_FAILURE);
2440 }
2441 
2442 static int
2443 usbgem_mac_stop(struct usbgem_dev *dp, int new_state, boolean_t graceful)
2444 {
2445 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2446 
2447 	/*
2448 	 * we must have writer lock for dev_state_lock
2449 	 */
2450 	ASSERT(new_state == MAC_STATE_STOPPED ||
2451 	    new_state == MAC_STATE_DISCONNECTED);
2452 
2453 	/* stop polling interrupt pipe */
2454 	if (dp->ugc.usbgc_interrupt && dp->intr_pipe) {
2455 		usb_pipe_stop_intr_polling(dp->intr_pipe, USB_FLAGS_SLEEP);
2456 	}
2457 
2458 	if (new_state == MAC_STATE_STOPPED || graceful) {
2459 		/* stop the nic hardware completely */
2460 		if (usbgem_hal_stop_chip(dp) != USB_SUCCESS) {
2461 			(void) usbgem_hal_reset_chip(dp);
2462 		}
2463 	}
2464 
2465 	/* stop preparing new rx packets and sending new packets */
2466 	dp->mac_state = new_state;
2467 
2468 	/* other processors must get mac_state correctly after here */
2469 	membar_producer();
2470 
2471 	/* cancel all requests we have sent */
2472 	usb_pipe_reset(dp->dip, dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0);
2473 	usb_pipe_reset(dp->dip, dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0);
2474 
2475 	DPRINTF(0, (CE_CONT,
2476 	    "!%s: %s: rx_busy_cnt:%d tx_busy_cnt:%d",
2477 	    dp->name, __func__, dp->rx_busy_cnt, dp->tx_busy_cnt));
2478 
2479 	/*
2480 	 * Here all rx packets has been cancelled and their call back
2481 	 * function has been exeuted, because we called usb_pipe_reset
2482 	 * synchronously.
2483 	 * So actually we just ensure rx_busy_cnt == 0.
2484 	 */
2485 	mutex_enter(&dp->rxlock);
2486 	while (dp->rx_busy_cnt > 0) {
2487 		cv_wait(&dp->rx_drain_cv, &dp->rxlock);
2488 	}
2489 	mutex_exit(&dp->rxlock);
2490 
2491 	DPRINTF(0, (CE_CONT, "!%s: %s: rx_busy_cnt is %d now",
2492 	    dp->name, __func__, dp->rx_busy_cnt));
2493 
2494 	mutex_enter(&dp->txlock);
2495 	while (dp->tx_busy_cnt > 0) {
2496 		cv_wait(&dp->tx_drain_cv, &dp->txlock);
2497 	}
2498 	mutex_exit(&dp->txlock);
2499 
2500 	DPRINTF(0, (CE_CONT, "!%s: %s: tx_busy_cnt is %d now",
2501 	    dp->name, __func__, dp->tx_busy_cnt));
2502 
2503 	return (USB_SUCCESS);
2504 }
2505 
2506 static int
2507 usbgem_add_multicast(struct usbgem_dev *dp, const uint8_t *ep)
2508 {
2509 	int	cnt;
2510 	int	err;
2511 
2512 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2513 
2514 	sema_p(&dp->rxfilter_lock);
2515 	if (dp->mc_count_req++ < USBGEM_MAXMC) {
2516 		/* append the new address at the end of the mclist */
2517 		cnt = dp->mc_count;
2518 		bcopy(ep, dp->mc_list[cnt].addr.ether_addr_octet,
2519 		    ETHERADDRL);
2520 		if (dp->ugc.usbgc_multicast_hash) {
2521 			dp->mc_list[cnt].hash =
2522 			    (*dp->ugc.usbgc_multicast_hash)(dp, ep);
2523 		}
2524 		dp->mc_count = cnt + 1;
2525 	}
2526 
2527 	if (dp->mc_count_req != dp->mc_count) {
2528 		/* multicast address list overflow */
2529 		dp->rxmode |= RXMODE_MULTI_OVF;
2530 	} else {
2531 		dp->rxmode &= ~RXMODE_MULTI_OVF;
2532 	}
2533 
2534 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
2535 		/* tell new multicast list to the hardware */
2536 		err = usbgem_hal_set_rx_filter(dp);
2537 	}
2538 	sema_v(&dp->rxfilter_lock);
2539 
2540 	return (err);
2541 }
2542 
2543 static int
2544 usbgem_remove_multicast(struct usbgem_dev *dp, const uint8_t *ep)
2545 {
2546 	size_t		len;
2547 	int		i;
2548 	int		cnt;
2549 	int		err;
2550 
2551 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2552 
2553 	sema_p(&dp->rxfilter_lock);
2554 	dp->mc_count_req--;
2555 	cnt = dp->mc_count;
2556 	for (i = 0; i < cnt; i++) {
2557 		if (bcmp(ep, &dp->mc_list[i].addr, ETHERADDRL)) {
2558 			continue;
2559 		}
2560 		/* shrink the mclist by copying forward */
2561 		len = (cnt - (i + 1)) * sizeof (*dp->mc_list);
2562 		if (len > 0) {
2563 			bcopy(&dp->mc_list[i+1], &dp->mc_list[i], len);
2564 		}
2565 		dp->mc_count--;
2566 		break;
2567 	}
2568 
2569 	if (dp->mc_count_req != dp->mc_count) {
2570 		/* multicast address list overflow */
2571 		dp->rxmode |= RXMODE_MULTI_OVF;
2572 	} else {
2573 		dp->rxmode &= ~RXMODE_MULTI_OVF;
2574 	}
2575 
2576 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
2577 		err = usbgem_hal_set_rx_filter(dp);
2578 	}
2579 	sema_v(&dp->rxfilter_lock);
2580 
2581 	return (err);
2582 }
2583 
2584 
2585 /* ============================================================== */
2586 /*
2587  * ioctl
2588  */
2589 /* ============================================================== */
2590 enum ioc_reply {
2591 	IOC_INVAL = -1,				/* bad, NAK with EINVAL	*/
2592 	IOC_DONE,				/* OK, reply sent	*/
2593 	IOC_ACK,				/* OK, just send ACK	*/
2594 	IOC_REPLY,				/* OK, just send reply	*/
2595 	IOC_RESTART_ACK,			/* OK, restart & ACK	*/
2596 	IOC_RESTART_REPLY			/* OK, restart & reply	*/
2597 };
2598 
2599 
2600 #ifdef USBGEM_CONFIG_MAC_PROP
2601 static int
2602 usbgem_get_def_val(struct usbgem_dev *dp, mac_prop_id_t pr_num,
2603     uint_t pr_valsize, void *pr_val)
2604 {
2605 	link_flowctrl_t fl;
2606 	int err = 0;
2607 
2608 	ASSERT(pr_valsize > 0);
2609 	switch (pr_num) {
2610 	case MAC_PROP_AUTONEG:
2611 		*(uint8_t *)pr_val =
2612 		    BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
2613 		break;
2614 
2615 	case MAC_PROP_FLOWCTRL:
2616 		if (pr_valsize < sizeof (link_flowctrl_t)) {
2617 			return (EINVAL);
2618 		}
2619 		switch (dp->ugc.usbgc_flow_control) {
2620 		case FLOW_CONTROL_NONE:
2621 			fl = LINK_FLOWCTRL_NONE;
2622 			break;
2623 		case FLOW_CONTROL_SYMMETRIC:
2624 			fl = LINK_FLOWCTRL_BI;
2625 			break;
2626 		case FLOW_CONTROL_TX_PAUSE:
2627 			fl = LINK_FLOWCTRL_TX;
2628 			break;
2629 		case FLOW_CONTROL_RX_PAUSE:
2630 			fl = LINK_FLOWCTRL_RX;
2631 			break;
2632 		}
2633 		bcopy(&fl, pr_val, sizeof (fl));
2634 		break;
2635 
2636 	case MAC_PROP_ADV_1000FDX_CAP:
2637 	case MAC_PROP_EN_1000FDX_CAP:
2638 		*(uint8_t *)pr_val =
2639 		    (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
2640 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
2641 		break;
2642 
2643 	case MAC_PROP_ADV_1000HDX_CAP:
2644 	case MAC_PROP_EN_1000HDX_CAP:
2645 		*(uint8_t *)pr_val =
2646 		    (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
2647 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
2648 		break;
2649 
2650 	case MAC_PROP_ADV_100T4_CAP:
2651 	case MAC_PROP_EN_100T4_CAP:
2652 		*(uint8_t *)pr_val =
2653 		    BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
2654 		break;
2655 
2656 	case MAC_PROP_ADV_100FDX_CAP:
2657 	case MAC_PROP_EN_100FDX_CAP:
2658 		*(uint8_t *)pr_val =
2659 		    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
2660 		break;
2661 
2662 	case MAC_PROP_ADV_100HDX_CAP:
2663 	case MAC_PROP_EN_100HDX_CAP:
2664 		*(uint8_t *)pr_val =
2665 		    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
2666 		break;
2667 
2668 	case MAC_PROP_ADV_10FDX_CAP:
2669 	case MAC_PROP_EN_10FDX_CAP:
2670 		*(uint8_t *)pr_val =
2671 		    BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
2672 		break;
2673 
2674 	case MAC_PROP_ADV_10HDX_CAP:
2675 	case MAC_PROP_EN_10HDX_CAP:
2676 		*(uint8_t *)pr_val =
2677 		    BOOLEAN(dp->mii_status & MII_STATUS_10);
2678 		break;
2679 
2680 	default:
2681 		err = ENOTSUP;
2682 		break;
2683 	}
2684 	return (err);
2685 }
2686 
2687 static void
2688 usbgem_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2689     mac_prop_info_handle_t prh)
2690 {
2691 	struct usbgem_dev *dp = arg;
2692 	link_flowctrl_t fl;
2693 
2694 	/*
2695 	 * By default permissions are read/write unless specified
2696 	 * otherwise by the driver.
2697 	 */
2698 
2699 	switch (pr_num) {
2700 	case MAC_PROP_DUPLEX:
2701 	case MAC_PROP_SPEED:
2702 	case MAC_PROP_STATUS:
2703 	case MAC_PROP_ADV_1000FDX_CAP:
2704 	case MAC_PROP_ADV_1000HDX_CAP:
2705 	case MAC_PROP_ADV_100FDX_CAP:
2706 	case MAC_PROP_ADV_100HDX_CAP:
2707 	case MAC_PROP_ADV_10FDX_CAP:
2708 	case MAC_PROP_ADV_10HDX_CAP:
2709 	case MAC_PROP_ADV_100T4_CAP:
2710 	case MAC_PROP_EN_100T4_CAP:
2711 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2712 		break;
2713 
2714 	case MAC_PROP_EN_1000FDX_CAP:
2715 		if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET_FD) == 0) {
2716 			mac_prop_info_set_default_uint8(prh,
2717 			    BOOLEAN(
2718 			    dp->mii_xstatus & MII_XSTATUS_1000BASET_FD));
2719 		} else if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX_FD)
2720 		    == 0) {
2721 			mac_prop_info_set_default_uint8(prh,
2722 			    BOOLEAN(
2723 			    dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD));
2724 		} else {
2725 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2726 		}
2727 		break;
2728 
2729 	case MAC_PROP_EN_1000HDX_CAP:
2730 		if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET) == 0) {
2731 			mac_prop_info_set_default_uint8(prh,
2732 			    BOOLEAN(
2733 			    dp->mii_xstatus & MII_XSTATUS_1000BASET));
2734 		} else if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX) == 0) {
2735 			mac_prop_info_set_default_uint8(prh,
2736 			    BOOLEAN(
2737 			    dp->mii_xstatus & MII_XSTATUS_1000BASEX));
2738 		} else {
2739 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2740 		}
2741 		break;
2742 
2743 	case MAC_PROP_EN_100FDX_CAP:
2744 		if ((dp->mii_status_ro & MII_STATUS_100_BASEX_FD) == 0) {
2745 			mac_prop_info_set_default_uint8(prh,
2746 			    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD));
2747 		} else {
2748 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2749 		}
2750 		break;
2751 
2752 	case MAC_PROP_EN_100HDX_CAP:
2753 		if ((dp->mii_status_ro & MII_STATUS_100_BASEX) == 0) {
2754 			mac_prop_info_set_default_uint8(prh,
2755 			    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX));
2756 		} else {
2757 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2758 		}
2759 		break;
2760 
2761 	case MAC_PROP_EN_10FDX_CAP:
2762 		if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) {
2763 			mac_prop_info_set_default_uint8(prh,
2764 			    BOOLEAN(dp->mii_status & MII_STATUS_10_FD));
2765 		} else {
2766 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2767 		}
2768 		break;
2769 
2770 	case MAC_PROP_EN_10HDX_CAP:
2771 		if ((dp->mii_status_ro & MII_STATUS_10) == 0) {
2772 			mac_prop_info_set_default_uint8(prh,
2773 			    BOOLEAN(dp->mii_status & MII_STATUS_10));
2774 		} else {
2775 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2776 		}
2777 		break;
2778 
2779 	case MAC_PROP_AUTONEG:
2780 		if ((dp->mii_status_ro & MII_STATUS_CANAUTONEG) == 0) {
2781 			mac_prop_info_set_default_uint8(prh,
2782 			    BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG));
2783 		} else {
2784 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2785 		}
2786 		break;
2787 
2788 	case MAC_PROP_FLOWCTRL:
2789 		switch (dp->ugc.usbgc_flow_control) {
2790 		case FLOW_CONTROL_NONE:
2791 			fl = LINK_FLOWCTRL_NONE;
2792 			break;
2793 		case FLOW_CONTROL_SYMMETRIC:
2794 			fl = LINK_FLOWCTRL_BI;
2795 			break;
2796 		case FLOW_CONTROL_TX_PAUSE:
2797 			fl = LINK_FLOWCTRL_TX;
2798 			break;
2799 		case FLOW_CONTROL_RX_PAUSE:
2800 			fl = LINK_FLOWCTRL_RX;
2801 			break;
2802 		}
2803 		mac_prop_info_set_default_link_flowctrl(prh, fl);
2804 		break;
2805 
2806 	case MAC_PROP_MTU:
2807 		mac_prop_info_set_range_uint32(prh,
2808 		    dp->ugc.usbgc_min_mtu, dp->ugc.usbgc_max_mtu);
2809 		break;
2810 
2811 	case MAC_PROP_PRIVATE:
2812 		break;
2813 	}
2814 }
2815 
2816 static int
2817 usbgem_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2818     uint_t pr_valsize, const void *pr_val)
2819 {
2820 	struct usbgem_dev *dp = arg;
2821 	int err = 0;
2822 	boolean_t	update = B_FALSE;
2823 	link_flowctrl_t flowctrl;
2824 	uint32_t cur_mtu, new_mtu;
2825 
2826 	rw_enter(&dp->dev_state_lock, RW_WRITER);
2827 	switch (pr_num) {
2828 	case MAC_PROP_EN_1000FDX_CAP:
2829 		if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET_FD) == 0 ||
2830 		    (dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX_FD) == 0) {
2831 			if (dp->anadv_1000fdx != *(uint8_t *)pr_val) {
2832 				dp->anadv_1000fdx = *(uint8_t *)pr_val;
2833 				update = B_TRUE;
2834 			}
2835 		} else {
2836 			err = ENOTSUP;
2837 		}
2838 		break;
2839 
2840 	case MAC_PROP_EN_1000HDX_CAP:
2841 		if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET) == 0 ||
2842 		    (dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX) == 0) {
2843 			if (dp->anadv_1000hdx != *(uint8_t *)pr_val) {
2844 				dp->anadv_1000hdx = *(uint8_t *)pr_val;
2845 				update = B_TRUE;
2846 			}
2847 		} else {
2848 			err = ENOTSUP;
2849 		}
2850 		break;
2851 
2852 	case MAC_PROP_EN_100FDX_CAP:
2853 		if ((dp->mii_status_ro & MII_STATUS_100_BASEX_FD) == 0) {
2854 			if (dp->anadv_100fdx != *(uint8_t *)pr_val) {
2855 				dp->anadv_100fdx = *(uint8_t *)pr_val;
2856 				update = B_TRUE;
2857 			}
2858 		} else {
2859 			err = ENOTSUP;
2860 		}
2861 		break;
2862 
2863 	case MAC_PROP_EN_100HDX_CAP:
2864 		if ((dp->mii_status_ro & MII_STATUS_100_BASEX) == 0) {
2865 			if (dp->anadv_100hdx != *(uint8_t *)pr_val) {
2866 				dp->anadv_100hdx = *(uint8_t *)pr_val;
2867 				update = B_TRUE;
2868 			}
2869 		} else {
2870 			err = ENOTSUP;
2871 		}
2872 		break;
2873 
2874 	case MAC_PROP_EN_10FDX_CAP:
2875 		if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) {
2876 			if (dp->anadv_10fdx != *(uint8_t *)pr_val) {
2877 				dp->anadv_10fdx = *(uint8_t *)pr_val;
2878 				update = B_TRUE;
2879 			}
2880 		} else {
2881 			err = ENOTSUP;
2882 		}
2883 		break;
2884 
2885 	case MAC_PROP_EN_10HDX_CAP:
2886 		if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) {
2887 			if (dp->anadv_10hdx != *(uint8_t *)pr_val) {
2888 				dp->anadv_10hdx = *(uint8_t *)pr_val;
2889 				update = B_TRUE;
2890 			}
2891 		} else {
2892 			err = ENOTSUP;
2893 		}
2894 		break;
2895 
2896 	case MAC_PROP_AUTONEG:
2897 		if ((dp->mii_status_ro & MII_STATUS_CANAUTONEG) == 0) {
2898 			if (dp->anadv_autoneg != *(uint8_t *)pr_val) {
2899 				dp->anadv_autoneg = *(uint8_t *)pr_val;
2900 				update = B_TRUE;
2901 			}
2902 		} else {
2903 			err = ENOTSUP;
2904 		}
2905 		break;
2906 
2907 	case MAC_PROP_FLOWCTRL:
2908 		bcopy(pr_val, &flowctrl, sizeof (flowctrl));
2909 
2910 		switch (flowctrl) {
2911 		default:
2912 			err = EINVAL;
2913 			break;
2914 
2915 		case LINK_FLOWCTRL_NONE:
2916 			if (dp->flow_control != FLOW_CONTROL_NONE) {
2917 				dp->flow_control = FLOW_CONTROL_NONE;
2918 				update = B_TRUE;
2919 			}
2920 			break;
2921 
2922 		case LINK_FLOWCTRL_RX:
2923 			if (dp->flow_control != FLOW_CONTROL_RX_PAUSE) {
2924 				dp->flow_control = FLOW_CONTROL_RX_PAUSE;
2925 				update = B_TRUE;
2926 			}
2927 			break;
2928 
2929 		case LINK_FLOWCTRL_TX:
2930 			if (dp->flow_control != FLOW_CONTROL_TX_PAUSE) {
2931 				dp->flow_control = FLOW_CONTROL_TX_PAUSE;
2932 				update = B_TRUE;
2933 			}
2934 			break;
2935 
2936 		case LINK_FLOWCTRL_BI:
2937 			if (dp->flow_control != FLOW_CONTROL_SYMMETRIC) {
2938 				dp->flow_control = FLOW_CONTROL_SYMMETRIC;
2939 				update = B_TRUE;
2940 			}
2941 			break;
2942 		}
2943 		break;
2944 
2945 	case MAC_PROP_ADV_1000FDX_CAP:
2946 	case MAC_PROP_ADV_1000HDX_CAP:
2947 	case MAC_PROP_ADV_100FDX_CAP:
2948 	case MAC_PROP_ADV_100HDX_CAP:
2949 	case MAC_PROP_ADV_10FDX_CAP:
2950 	case MAC_PROP_ADV_10HDX_CAP:
2951 	case MAC_PROP_STATUS:
2952 	case MAC_PROP_SPEED:
2953 	case MAC_PROP_DUPLEX:
2954 		err = ENOTSUP; /* read-only prop. Can't set this. */
2955 		break;
2956 
2957 	case MAC_PROP_MTU:
2958 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
2959 		if (new_mtu != dp->mtu) {
2960 			err = EINVAL;
2961 		}
2962 		break;
2963 
2964 	case MAC_PROP_PRIVATE:
2965 		err = ENOTSUP;
2966 		break;
2967 
2968 	default:
2969 		err = ENOTSUP;
2970 		break;
2971 	}
2972 
2973 	if (update) {
2974 		/* sync with PHY */
2975 		usbgem_choose_forcedmode(dp);
2976 		dp->mii_state = MII_STATE_UNKNOWN;
2977 		cv_signal(&dp->link_watcher_wait_cv);
2978 	}
2979 	rw_exit(&dp->dev_state_lock);
2980 	return (err);
2981 }
2982 
2983 static int
2984 usbgem_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2985     uint_t pr_valsize, void *pr_val)
2986 {
2987 	struct usbgem_dev *dp = arg;
2988 	int err = 0;
2989 	link_flowctrl_t flowctrl;
2990 	uint64_t tmp = 0;
2991 
2992 	if (pr_valsize == 0) {
2993 		return (EINVAL);
2994 	}
2995 
2996 	bzero(pr_val, pr_valsize);
2997 	rw_enter(&dp->dev_state_lock, RW_READER);
2998 	switch (pr_num) {
2999 	case MAC_PROP_DUPLEX:
3000 		if (pr_valsize >= sizeof (link_duplex_t)) {
3001 			if (dp->mii_state != MII_STATE_LINKUP) {
3002 				*(link_duplex_t *)pr_val = LINK_DUPLEX_UNKNOWN;
3003 			} else if (dp->full_duplex) {
3004 				*(link_duplex_t *)pr_val = LINK_DUPLEX_FULL;
3005 			} else {
3006 				*(link_duplex_t *)pr_val = LINK_DUPLEX_HALF;
3007 			}
3008 		} else {
3009 			err = EINVAL;
3010 		}
3011 		break;
3012 	case MAC_PROP_SPEED:
3013 		if (pr_valsize >= sizeof (uint64_t)) {
3014 			switch (dp->speed) {
3015 			case USBGEM_SPD_1000:
3016 				tmp = 1000000000;
3017 				break;
3018 			case USBGEM_SPD_100:
3019 				tmp = 100000000;
3020 				break;
3021 			case USBGEM_SPD_10:
3022 				tmp = 10000000;
3023 				break;
3024 			default:
3025 				tmp = 0;
3026 			}
3027 			bcopy(&tmp, pr_val, sizeof (tmp));
3028 		} else {
3029 			err = EINVAL;
3030 		}
3031 		break;
3032 
3033 	case MAC_PROP_AUTONEG:
3034 		*(uint8_t *)pr_val = dp->anadv_autoneg;
3035 		break;
3036 
3037 	case MAC_PROP_FLOWCTRL:
3038 		if (pr_valsize >= sizeof (link_flowctrl_t)) {
3039 			switch (dp->flow_control) {
3040 			case FLOW_CONTROL_NONE:
3041 				flowctrl = LINK_FLOWCTRL_NONE;
3042 				break;
3043 			case FLOW_CONTROL_RX_PAUSE:
3044 				flowctrl = LINK_FLOWCTRL_RX;
3045 				break;
3046 			case FLOW_CONTROL_TX_PAUSE:
3047 				flowctrl = LINK_FLOWCTRL_TX;
3048 				break;
3049 			case FLOW_CONTROL_SYMMETRIC:
3050 				flowctrl = LINK_FLOWCTRL_BI;
3051 				break;
3052 			}
3053 			bcopy(&flowctrl, pr_val, sizeof (flowctrl));
3054 		} else {
3055 			err = EINVAL;
3056 		}
3057 		break;
3058 
3059 	case MAC_PROP_ADV_1000FDX_CAP:
3060 	case MAC_PROP_ADV_1000HDX_CAP:
3061 	case MAC_PROP_ADV_100FDX_CAP:
3062 	case MAC_PROP_ADV_100HDX_CAP:
3063 	case MAC_PROP_ADV_10FDX_CAP:
3064 	case MAC_PROP_ADV_10HDX_CAP:
3065 	case MAC_PROP_ADV_100T4_CAP:
3066 		usbgem_get_def_val(dp, pr_num, pr_valsize, pr_val);
3067 		break;
3068 
3069 	case MAC_PROP_EN_1000FDX_CAP:
3070 		*(uint8_t *)pr_val = dp->anadv_1000fdx;
3071 		break;
3072 
3073 	case MAC_PROP_EN_1000HDX_CAP:
3074 		*(uint8_t *)pr_val = dp->anadv_1000hdx;
3075 		break;
3076 
3077 	case MAC_PROP_EN_100FDX_CAP:
3078 		*(uint8_t *)pr_val = dp->anadv_100fdx;
3079 		break;
3080 
3081 	case MAC_PROP_EN_100HDX_CAP:
3082 		*(uint8_t *)pr_val = dp->anadv_100hdx;
3083 		break;
3084 
3085 	case MAC_PROP_EN_10FDX_CAP:
3086 		*(uint8_t *)pr_val = dp->anadv_10fdx;
3087 		break;
3088 
3089 	case MAC_PROP_EN_10HDX_CAP:
3090 		*(uint8_t *)pr_val = dp->anadv_10hdx;
3091 		break;
3092 
3093 	case MAC_PROP_EN_100T4_CAP:
3094 		*(uint8_t *)pr_val = dp->anadv_100t4;
3095 		break;
3096 
3097 	case MAC_PROP_PRIVATE:
3098 		err = ENOTSUP;
3099 		break;
3100 
3101 	default:
3102 		err = ENOTSUP;
3103 		break;
3104 	}
3105 
3106 	rw_exit(&dp->dev_state_lock);
3107 	return (err);
3108 }
3109 #endif /* USBGEM_CONFIG_MAC_PROP */
3110 
3111 static void
3112 usbgem_mac_ioctl(struct usbgem_dev *dp, queue_t *wq, mblk_t *mp)
3113 {
3114 	struct iocblk	*iocp;
3115 	enum ioc_reply	status;
3116 
3117 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3118 
3119 	/*
3120 	 * Validate the command before bothering with the mutex ...
3121 	 */
3122 	iocp = (void *)mp->b_rptr;
3123 	iocp->ioc_error = 0;
3124 
3125 	DPRINTF(1, (CE_CONT, "%s: %s cmd:0x%x", dp->name, __func__,
3126 	    iocp->ioc_cmd));
3127 
3128 	miocnak(wq, mp, 0, EINVAL);
3129 }
3130 
3131 #ifndef SYS_MAC_H
3132 #define	XCVR_UNDEFINED	0
3133 #define	XCVR_NONE	1
3134 #define	XCVR_10		2
3135 #define	XCVR_100T4	3
3136 #define	XCVR_100X	4
3137 #define	XCVR_100T2	5
3138 #define	XCVR_1000X	6
3139 #define	XCVR_1000T	7
3140 #endif
3141 static int
3142 usbgem_mac_xcvr_inuse(struct usbgem_dev *dp)
3143 {
3144 	int	val = XCVR_UNDEFINED;
3145 
3146 	if ((dp->mii_status & MII_STATUS_XSTATUS) == 0) {
3147 		if (dp->mii_status & MII_STATUS_100_BASE_T4) {
3148 			val = XCVR_100T4;
3149 		} else if (dp->mii_status &
3150 		    (MII_STATUS_100_BASEX_FD |
3151 		    MII_STATUS_100_BASEX)) {
3152 			val = XCVR_100X;
3153 		} else if (dp->mii_status &
3154 		    (MII_STATUS_100_BASE_T2_FD |
3155 		    MII_STATUS_100_BASE_T2)) {
3156 			val = XCVR_100T2;
3157 		} else if (dp->mii_status &
3158 		    (MII_STATUS_10_FD | MII_STATUS_10)) {
3159 			val = XCVR_10;
3160 		}
3161 	} else if (dp->mii_xstatus &
3162 	    (MII_XSTATUS_1000BASET_FD | MII_XSTATUS_1000BASET)) {
3163 		val = XCVR_1000T;
3164 	} else if (dp->mii_xstatus &
3165 	    (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASEX)) {
3166 		val = XCVR_1000X;
3167 	}
3168 
3169 	return (val);
3170 }
3171 
3172 /* ============================================================== */
3173 /*
3174  * GLDv3 interface
3175  */
3176 /* ============================================================== */
3177 static int	usbgem_m_getstat(void *, uint_t, uint64_t *);
3178 static int	usbgem_m_start(void *);
3179 static void	usbgem_m_stop(void *);
3180 static int	usbgem_m_setpromisc(void *, boolean_t);
3181 static int	usbgem_m_multicst(void *, boolean_t, const uint8_t *);
3182 static int	usbgem_m_unicst(void *, const uint8_t *);
3183 static mblk_t	*usbgem_m_tx(void *, mblk_t *);
3184 static void	usbgem_m_ioctl(void *, queue_t *, mblk_t *);
3185 static int	usbgem_m_setprop(void *, const char *, mac_prop_id_t,
3186     uint_t, const void *);
3187 static int	usbgem_m_getprop(void *, const char *, mac_prop_id_t,
3188     uint_t, void *);
3189 
3190 static mac_callbacks_t gem_m_callbacks = {
3191 	MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
3192 	usbgem_m_getstat,
3193 	usbgem_m_start,
3194 	usbgem_m_stop,
3195 	usbgem_m_setpromisc,
3196 	usbgem_m_multicst,
3197 	usbgem_m_unicst,
3198 	usbgem_m_tx,
3199 	NULL,
3200 	usbgem_m_ioctl,
3201 	NULL, /* m_getcapab */
3202 	NULL,
3203 	NULL,
3204 	usbgem_m_setprop,
3205 	usbgem_m_getprop,
3206 	usbgem_m_propinfo,
3207 };
3208 
3209 static int
3210 usbgem_m_start(void *arg)
3211 {
3212 	int	ret;
3213 	int	err;
3214 	struct usbgem_dev *dp = arg;
3215 
3216 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3217 
3218 	err = EIO;
3219 
3220 	rw_enter(&dp->dev_state_lock, RW_WRITER);
3221 	dp->nic_state = NIC_STATE_ONLINE;
3222 
3223 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
3224 		err = 0;
3225 		goto x;
3226 	}
3227 	if (usbgem_mac_init(dp) != USB_SUCCESS) {
3228 		goto x;
3229 	}
3230 
3231 	/* initialize rx filter state */
3232 	sema_p(&dp->rxfilter_lock);
3233 	dp->mc_count = 0;
3234 	dp->mc_count_req = 0;
3235 
3236 	bcopy(dp->dev_addr.ether_addr_octet,
3237 	    dp->cur_addr.ether_addr_octet, ETHERADDRL);
3238 	dp->rxmode |= RXMODE_ENABLE;
3239 
3240 	ret = usbgem_hal_set_rx_filter(dp);
3241 	sema_v(&dp->rxfilter_lock);
3242 
3243 	if (ret != USB_SUCCESS) {
3244 		goto x;
3245 	}
3246 
3247 	if (dp->mii_state == MII_STATE_LINKUP) {
3248 		/* setup media mode if the link have been up */
3249 		if (usbgem_hal_set_media(dp) != USB_SUCCESS) {
3250 			goto x;
3251 		}
3252 		if (usbgem_mac_start(dp) != USB_SUCCESS) {
3253 			goto x;
3254 		}
3255 	}
3256 
3257 	err = 0;
3258 x:
3259 	rw_exit(&dp->dev_state_lock);
3260 	return (err);
3261 }
3262 
3263 static void
3264 usbgem_m_stop(void *arg)
3265 {
3266 	struct usbgem_dev	*dp = arg;
3267 
3268 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3269 
3270 	/* stop rx gracefully */
3271 	rw_enter(&dp->dev_state_lock, RW_READER);
3272 	sema_p(&dp->rxfilter_lock);
3273 	dp->rxmode &= ~RXMODE_ENABLE;
3274 
3275 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
3276 		(void) usbgem_hal_set_rx_filter(dp);
3277 	}
3278 	sema_v(&dp->rxfilter_lock);
3279 	rw_exit(&dp->dev_state_lock);
3280 
3281 	/* make the nic state inactive */
3282 	rw_enter(&dp->dev_state_lock, RW_WRITER);
3283 	dp->nic_state = NIC_STATE_STOPPED;
3284 
3285 	/* stop mac completely */
3286 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
3287 		(void) usbgem_mac_stop(dp, MAC_STATE_STOPPED, STOP_GRACEFUL);
3288 	}
3289 	rw_exit(&dp->dev_state_lock);
3290 }
3291 
3292 static int
3293 usbgem_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
3294 {
3295 	int	err;
3296 	int	ret;
3297 	struct usbgem_dev	*dp = arg;
3298 
3299 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3300 
3301 	rw_enter(&dp->dev_state_lock, RW_READER);
3302 	if (add) {
3303 		ret = usbgem_add_multicast(dp, ep);
3304 	} else {
3305 		ret = usbgem_remove_multicast(dp, ep);
3306 	}
3307 	rw_exit(&dp->dev_state_lock);
3308 
3309 	err = 0;
3310 	if (ret != USB_SUCCESS) {
3311 #ifdef GEM_CONFIG_FMA
3312 		ddi_fm_service_impact(dp->dip, DDI_SERVICE_DEGRADED);
3313 #endif
3314 		err = EIO;
3315 	}
3316 
3317 	return (err);
3318 }
3319 
3320 static int
3321 usbgem_m_setpromisc(void *arg, boolean_t on)
3322 {
3323 	int	err;
3324 	struct usbgem_dev	*dp = arg;
3325 
3326 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3327 
3328 	rw_enter(&dp->dev_state_lock, RW_READER);
3329 
3330 	sema_p(&dp->rxfilter_lock);
3331 	if (on) {
3332 		dp->rxmode |= RXMODE_PROMISC;
3333 	} else {
3334 		dp->rxmode &= ~RXMODE_PROMISC;
3335 	}
3336 
3337 	err = 0;
3338 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
3339 		if (usbgem_hal_set_rx_filter(dp) != USB_SUCCESS) {
3340 			err = EIO;
3341 		}
3342 	}
3343 	sema_v(&dp->rxfilter_lock);
3344 
3345 	rw_exit(&dp->dev_state_lock);
3346 
3347 #ifdef GEM_CONFIG_FMA
3348 	if (err != 0) {
3349 		ddi_fm_service_impact(dp->dip, DDI_SERVICE_DEGRADED);
3350 	}
3351 #endif
3352 	return (err);
3353 }
3354 
3355 int
3356 usbgem_m_getstat(void *arg, uint_t stat, uint64_t *valp)
3357 {
3358 	uint64_t	val;
3359 	struct usbgem_dev	*dp = arg;
3360 	struct usbgem_stats	*gstp = &dp->stats;
3361 
3362 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3363 
3364 	rw_enter(&dp->dev_state_lock, RW_READER);
3365 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
3366 		rw_exit(&dp->dev_state_lock);
3367 		return (0);
3368 	}
3369 
3370 	/* LINTED */
3371 	if (usbgem_hal_get_stats(dp) != USB_SUCCESS) {
3372 #ifdef GEM_CONFIG_FMA
3373 		rw_exit(&dp->dev_state_lock);
3374 		ddi_fm_service_impact(dp->dip, DDI_SERVICE_DEGRADED);
3375 		return (EIO);
3376 #endif
3377 	}
3378 	rw_exit(&dp->dev_state_lock);
3379 
3380 	switch (stat) {
3381 	case MAC_STAT_IFSPEED:
3382 		val = usbgem_speed_value[dp->speed] *1000000ull;
3383 		break;
3384 
3385 	case MAC_STAT_MULTIRCV:
3386 		val = gstp->rmcast;
3387 		break;
3388 
3389 	case MAC_STAT_BRDCSTRCV:
3390 		val = gstp->rbcast;
3391 		break;
3392 
3393 	case MAC_STAT_MULTIXMT:
3394 		val = gstp->omcast;
3395 		break;
3396 
3397 	case MAC_STAT_BRDCSTXMT:
3398 		val = gstp->obcast;
3399 		break;
3400 
3401 	case MAC_STAT_NORCVBUF:
3402 		val = gstp->norcvbuf + gstp->missed;
3403 		break;
3404 
3405 	case MAC_STAT_IERRORS:
3406 		val = gstp->errrcv;
3407 		break;
3408 
3409 	case MAC_STAT_NOXMTBUF:
3410 		val = gstp->noxmtbuf;
3411 		break;
3412 
3413 	case MAC_STAT_OERRORS:
3414 		val = gstp->errxmt;
3415 		break;
3416 
3417 	case MAC_STAT_COLLISIONS:
3418 		val = gstp->collisions;
3419 		break;
3420 
3421 	case MAC_STAT_RBYTES:
3422 		val = gstp->rbytes;
3423 		break;
3424 
3425 	case MAC_STAT_IPACKETS:
3426 		val = gstp->rpackets;
3427 		break;
3428 
3429 	case MAC_STAT_OBYTES:
3430 		val = gstp->obytes;
3431 		break;
3432 
3433 	case MAC_STAT_OPACKETS:
3434 		val = gstp->opackets;
3435 		break;
3436 
3437 	case MAC_STAT_UNDERFLOWS:
3438 		val = gstp->underflow;
3439 		break;
3440 
3441 	case MAC_STAT_OVERFLOWS:
3442 		val = gstp->overflow;
3443 		break;
3444 
3445 	case ETHER_STAT_ALIGN_ERRORS:
3446 		val = gstp->frame;
3447 		break;
3448 
3449 	case ETHER_STAT_FCS_ERRORS:
3450 		val = gstp->crc;
3451 		break;
3452 
3453 	case ETHER_STAT_FIRST_COLLISIONS:
3454 		val = gstp->first_coll;
3455 		break;
3456 
3457 	case ETHER_STAT_MULTI_COLLISIONS:
3458 		val = gstp->multi_coll;
3459 		break;
3460 
3461 	case ETHER_STAT_SQE_ERRORS:
3462 		val = gstp->sqe;
3463 		break;
3464 
3465 	case ETHER_STAT_DEFER_XMTS:
3466 		val = gstp->defer;
3467 		break;
3468 
3469 	case ETHER_STAT_TX_LATE_COLLISIONS:
3470 		val = gstp->xmtlatecoll;
3471 		break;
3472 
3473 	case ETHER_STAT_EX_COLLISIONS:
3474 		val = gstp->excoll;
3475 		break;
3476 
3477 	case ETHER_STAT_MACXMT_ERRORS:
3478 		val = gstp->xmit_internal_err;
3479 		break;
3480 
3481 	case ETHER_STAT_CARRIER_ERRORS:
3482 		val = gstp->nocarrier;
3483 		break;
3484 
3485 	case ETHER_STAT_TOOLONG_ERRORS:
3486 		val = gstp->frame_too_long;
3487 		break;
3488 
3489 	case ETHER_STAT_MACRCV_ERRORS:
3490 		val = gstp->rcv_internal_err;
3491 		break;
3492 
3493 	case ETHER_STAT_XCVR_ADDR:
3494 		val = dp->mii_phy_addr;
3495 		break;
3496 
3497 	case ETHER_STAT_XCVR_ID:
3498 		val = dp->mii_phy_id;
3499 		break;
3500 
3501 	case ETHER_STAT_XCVR_INUSE:
3502 		val = usbgem_mac_xcvr_inuse(dp);
3503 		break;
3504 
3505 	case ETHER_STAT_CAP_1000FDX:
3506 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
3507 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
3508 		break;
3509 
3510 	case ETHER_STAT_CAP_1000HDX:
3511 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
3512 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
3513 		break;
3514 
3515 	case ETHER_STAT_CAP_100FDX:
3516 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
3517 		break;
3518 
3519 	case ETHER_STAT_CAP_100HDX:
3520 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
3521 		break;
3522 
3523 	case ETHER_STAT_CAP_10FDX:
3524 		val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
3525 		break;
3526 
3527 	case ETHER_STAT_CAP_10HDX:
3528 		val = BOOLEAN(dp->mii_status & MII_STATUS_10);
3529 		break;
3530 
3531 	case ETHER_STAT_CAP_ASMPAUSE:
3532 		val = dp->ugc.usbgc_flow_control > FLOW_CONTROL_SYMMETRIC;
3533 		break;
3534 
3535 	case ETHER_STAT_CAP_PAUSE:
3536 		val = dp->ugc.usbgc_flow_control != FLOW_CONTROL_NONE;
3537 		break;
3538 
3539 	case ETHER_STAT_CAP_AUTONEG:
3540 		val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
3541 		break;
3542 
3543 	case ETHER_STAT_ADV_CAP_1000FDX:
3544 		val = dp->anadv_1000fdx;
3545 		break;
3546 
3547 	case ETHER_STAT_ADV_CAP_1000HDX:
3548 		val = dp->anadv_1000hdx;
3549 		break;
3550 
3551 	case ETHER_STAT_ADV_CAP_100FDX:
3552 		val = dp->anadv_100fdx;
3553 		break;
3554 
3555 	case ETHER_STAT_ADV_CAP_100HDX:
3556 		val = dp->anadv_100hdx;
3557 		break;
3558 
3559 	case ETHER_STAT_ADV_CAP_10FDX:
3560 		val = dp->anadv_10fdx;
3561 		break;
3562 
3563 	case ETHER_STAT_ADV_CAP_10HDX:
3564 		val = dp->anadv_10hdx;
3565 		break;
3566 
3567 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
3568 		val = dp->anadv_asmpause;
3569 		break;
3570 
3571 	case ETHER_STAT_ADV_CAP_PAUSE:
3572 		val = dp->anadv_pause;
3573 		break;
3574 
3575 	case ETHER_STAT_ADV_CAP_AUTONEG:
3576 		val = dp->anadv_autoneg;
3577 		break;
3578 
3579 	case ETHER_STAT_LP_CAP_1000FDX:
3580 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
3581 		break;
3582 
3583 	case ETHER_STAT_LP_CAP_1000HDX:
3584 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
3585 		break;
3586 
3587 	case ETHER_STAT_LP_CAP_100FDX:
3588 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
3589 		break;
3590 
3591 	case ETHER_STAT_LP_CAP_100HDX:
3592 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
3593 		break;
3594 
3595 	case ETHER_STAT_LP_CAP_10FDX:
3596 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
3597 		break;
3598 
3599 	case ETHER_STAT_LP_CAP_10HDX:
3600 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
3601 		break;
3602 
3603 	case ETHER_STAT_LP_CAP_ASMPAUSE:
3604 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASM_DIR);
3605 		break;
3606 
3607 	case ETHER_STAT_LP_CAP_PAUSE:
3608 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE);
3609 		break;
3610 
3611 	case ETHER_STAT_LP_CAP_AUTONEG:
3612 		val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3613 		break;
3614 
3615 	case ETHER_STAT_LINK_ASMPAUSE:
3616 		val = BOOLEAN(dp->flow_control & 2);
3617 		break;
3618 
3619 	case ETHER_STAT_LINK_PAUSE:
3620 		val = BOOLEAN(dp->flow_control & 1);
3621 		break;
3622 
3623 	case ETHER_STAT_LINK_AUTONEG:
3624 		val = dp->anadv_autoneg &&
3625 		    BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3626 		break;
3627 
3628 	case ETHER_STAT_LINK_DUPLEX:
3629 		val = (dp->mii_state == MII_STATE_LINKUP) ?
3630 		    (dp->full_duplex ? 2 : 1) : 0;
3631 		break;
3632 
3633 	case ETHER_STAT_TOOSHORT_ERRORS:
3634 		val = gstp->runt;
3635 		break;
3636 #ifdef NEVER	/* it doesn't make sense */
3637 	case ETHER_STAT_CAP_REMFAULT:
3638 		val = B_TRUE;
3639 		break;
3640 
3641 	case ETHER_STAT_ADV_REMFAULT:
3642 		val = dp->anadv_remfault;
3643 		break;
3644 #endif
3645 	case ETHER_STAT_LP_REMFAULT:
3646 		val = BOOLEAN(dp->mii_lpable & MII_AN_ADVERT_REMFAULT);
3647 		break;
3648 
3649 	case ETHER_STAT_JABBER_ERRORS:
3650 		val = gstp->jabber;
3651 		break;
3652 
3653 	case ETHER_STAT_CAP_100T4:
3654 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
3655 		break;
3656 
3657 	case ETHER_STAT_ADV_CAP_100T4:
3658 		val = dp->anadv_100t4;
3659 		break;
3660 
3661 	case ETHER_STAT_LP_CAP_100T4:
3662 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4);
3663 		break;
3664 
3665 	default:
3666 #if GEM_DEBUG_LEVEL > 2
3667 		cmn_err(CE_WARN,
3668 		    "%s: unrecognized parameter value = %d",
3669 		    __func__, stat);
3670 #endif
3671 		*valp = 0;
3672 		return (ENOTSUP);
3673 	}
3674 
3675 	*valp = val;
3676 
3677 	return (0);
3678 }
3679 
3680 static int
3681 usbgem_m_unicst(void *arg, const uint8_t *mac)
3682 {
3683 	int	err;
3684 	struct usbgem_dev	*dp = arg;
3685 
3686 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3687 
3688 	rw_enter(&dp->dev_state_lock, RW_READER);
3689 
3690 	sema_p(&dp->rxfilter_lock);
3691 	bcopy(mac, dp->cur_addr.ether_addr_octet, ETHERADDRL);
3692 	dp->rxmode |= RXMODE_ENABLE;
3693 
3694 	err = 0;
3695 	if (dp->mac_state != MAC_STATE_DISCONNECTED) {
3696 		if (usbgem_hal_set_rx_filter(dp) != USB_SUCCESS) {
3697 			err = EIO;
3698 		}
3699 	}
3700 	sema_v(&dp->rxfilter_lock);
3701 	rw_exit(&dp->dev_state_lock);
3702 
3703 #ifdef GEM_CONFIG_FMA
3704 	if (err != 0) {
3705 		ddi_fm_service_impact(dp->dip, DDI_SERVICE_DEGRADED);
3706 	}
3707 #endif
3708 	return (err);
3709 }
3710 
3711 /*
3712  * usbgem_m_tx is used only for sending data packets into ethernet wire.
3713  */
3714 static mblk_t *
3715 usbgem_m_tx(void *arg, mblk_t *mp_head)
3716 {
3717 	int	limit;
3718 	mblk_t	*mp;
3719 	mblk_t	*nmp;
3720 	struct usbgem_dev	*dp = arg;
3721 
3722 	DPRINTF(4, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3723 
3724 	mp = mp_head;
3725 
3726 	rw_enter(&dp->dev_state_lock, RW_READER);
3727 
3728 	if (dp->mii_state != MII_STATE_LINKUP ||
3729 	    dp->mac_state != MAC_STATE_ONLINE) {
3730 		/* some nics hate to send packets during the link is down */
3731 		for (; mp; mp = nmp) {
3732 			nmp = mp->b_next;
3733 			mp->b_next = NULL;
3734 			freemsg(mp);
3735 		}
3736 		goto x;
3737 	}
3738 
3739 	ASSERT(dp->nic_state == NIC_STATE_ONLINE);
3740 
3741 	limit = dp->tx_max_packets;
3742 	for (; limit-- && mp; mp = nmp) {
3743 		nmp = mp->b_next;
3744 		mp->b_next = NULL;
3745 		if (usbgem_send_common(dp, mp,
3746 		    (limit == 0 && nmp) ? 1 : 0)) {
3747 			mp->b_next = nmp;
3748 			break;
3749 		}
3750 	}
3751 #ifdef CONFIG_TX_LIMITER
3752 	if (mp == mp_head) {
3753 		/* no packets were sent, descrease allocation limit */
3754 		mutex_enter(&dp->txlock);
3755 		dp->tx_max_packets = max(dp->tx_max_packets - 1, 1);
3756 		mutex_exit(&dp->txlock);
3757 	}
3758 #endif
3759 x:
3760 	rw_exit(&dp->dev_state_lock);
3761 
3762 	return (mp);
3763 }
3764 
3765 static void
3766 usbgem_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
3767 {
3768 	struct usbgem_dev	*dp = arg;
3769 
3770 	DPRINTF(1, (CE_CONT, "!%s: %s: called",
3771 	    ((struct usbgem_dev *)arg)->name, __func__));
3772 
3773 	rw_enter(&dp->dev_state_lock, RW_READER);
3774 	usbgem_mac_ioctl((struct usbgem_dev *)arg, wq, mp);
3775 	rw_exit(&dp->dev_state_lock);
3776 }
3777 
3778 static void
3779 usbgem_gld3_init(struct usbgem_dev *dp, mac_register_t *macp)
3780 {
3781 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
3782 	macp->m_driver = dp;
3783 	macp->m_dip = dp->dip;
3784 	macp->m_src_addr = dp->dev_addr.ether_addr_octet;
3785 	macp->m_callbacks = &gem_m_callbacks;
3786 	macp->m_min_sdu = 0;
3787 	macp->m_max_sdu = dp->mtu;
3788 
3789 	if (dp->misc_flag & USBGEM_VLAN) {
3790 		macp->m_margin = VTAG_SIZE;
3791 	}
3792 }
3793 
3794 /* ======================================================================== */
3795 /*
3796  * .conf interface
3797  */
3798 /* ======================================================================== */
3799 void
3800 usbgem_generate_macaddr(struct usbgem_dev *dp, uint8_t *mac)
3801 {
3802 	extern char	hw_serial[];
3803 	char		*hw_serial_p;
3804 	int		i;
3805 	uint64_t	val;
3806 	uint64_t	key;
3807 
3808 	cmn_err(CE_NOTE,
3809 	    "!%s: using temp ether address,"
3810 	    " do not use this for long time",
3811 	    dp->name);
3812 
3813 	/* prefer a fixed address for DHCP */
3814 	hw_serial_p = &hw_serial[0];
3815 	val = stoi(&hw_serial_p);
3816 
3817 	key = 0;
3818 	for (i = 0; i < USBGEM_NAME_LEN; i++) {
3819 		if (dp->name[i] == 0) {
3820 			break;
3821 		}
3822 		key ^= dp->name[i];
3823 	}
3824 	key ^= ddi_get_instance(dp->dip);
3825 	val ^= key << 32;
3826 
3827 	/* generate a local address */
3828 	mac[0] = 0x02;
3829 	mac[1] = (uint8_t)(val >> 32);
3830 	mac[2] = (uint8_t)(val >> 24);
3831 	mac[3] = (uint8_t)(val >> 16);
3832 	mac[4] = (uint8_t)(val >> 8);
3833 	mac[5] = (uint8_t)val;
3834 }
3835 
3836 boolean_t
3837 usbgem_get_mac_addr_conf(struct usbgem_dev *dp)
3838 {
3839 	char		propname[32];
3840 	char		*valstr;
3841 	uint8_t		mac[ETHERADDRL];
3842 	char		*cp;
3843 	int		c;
3844 	int		i;
3845 	int		j;
3846 	uint8_t		v;
3847 	uint8_t		d;
3848 	uint8_t		ored;
3849 
3850 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3851 	/*
3852 	 * Get ethernet address from .conf file
3853 	 */
3854 	(void) sprintf(propname, "mac-addr");
3855 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dp->dip,
3856 	    DDI_PROP_DONTPASS, propname, &valstr)) != DDI_PROP_SUCCESS) {
3857 		return (B_FALSE);
3858 	}
3859 
3860 	if (strlen(valstr) != ETHERADDRL*3-1) {
3861 		goto syntax_err;
3862 	}
3863 
3864 	cp = valstr;
3865 	j = 0;
3866 	ored = 0;
3867 	for (;;) {
3868 		v = 0;
3869 		for (i = 0; i < 2; i++) {
3870 			c = *cp++;
3871 
3872 			if (c >= 'a' && c <= 'f') {
3873 				d = c - 'a' + 10;
3874 			} else if (c >= 'A' && c <= 'F') {
3875 				d = c - 'A' + 10;
3876 			} else if (c >= '0' && c <= '9') {
3877 				d = c - '0';
3878 			} else {
3879 				goto syntax_err;
3880 			}
3881 			v = (v << 4) | d;
3882 		}
3883 
3884 		mac[j++] = v;
3885 		ored |= v;
3886 		if (j == ETHERADDRL) {
3887 			/* done */
3888 			break;
3889 		}
3890 
3891 		c = *cp++;
3892 		if (c != ':') {
3893 			goto syntax_err;
3894 		}
3895 	}
3896 
3897 	if (ored == 0) {
3898 		usbgem_generate_macaddr(dp, mac);
3899 	}
3900 	for (i = 0; i < ETHERADDRL; i++) {
3901 		dp->dev_addr.ether_addr_octet[i] = mac[i];
3902 	}
3903 	ddi_prop_free(valstr);
3904 	return (B_TRUE);
3905 
3906 syntax_err:
3907 	cmn_err(CE_CONT,
3908 	    "!%s: read mac addr: trying .conf: syntax err %s",
3909 	    dp->name, valstr);
3910 	ddi_prop_free(valstr);
3911 
3912 	return (B_FALSE);
3913 }
3914 
3915 static void
3916 usbgem_read_conf(struct usbgem_dev *dp)
3917 {
3918 	int	val;
3919 
3920 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3921 
3922 	/*
3923 	 * Get media mode infomation from .conf file
3924 	 */
3925 	dp->anadv_autoneg = usbgem_prop_get_int(dp, "adv_autoneg_cap", 1) != 0;
3926 	dp->anadv_1000fdx = usbgem_prop_get_int(dp, "adv_1000fdx_cap", 1) != 0;
3927 	dp->anadv_1000hdx = usbgem_prop_get_int(dp, "adv_1000hdx_cap", 1) != 0;
3928 	dp->anadv_100t4 = usbgem_prop_get_int(dp, "adv_100T4_cap", 1) != 0;
3929 	dp->anadv_100fdx = usbgem_prop_get_int(dp, "adv_100fdx_cap", 1) != 0;
3930 	dp->anadv_100hdx = usbgem_prop_get_int(dp, "adv_100hdx_cap", 1) != 0;
3931 	dp->anadv_10fdx = usbgem_prop_get_int(dp, "adv_10fdx_cap", 1) != 0;
3932 	dp->anadv_10hdx = usbgem_prop_get_int(dp, "adv_10hdx_cap", 1) != 0;
3933 	dp->anadv_1000t_ms = usbgem_prop_get_int(dp, "adv_1000t_ms", 0);
3934 
3935 	if ((ddi_prop_exists(DDI_DEV_T_ANY, dp->dip,
3936 	    DDI_PROP_DONTPASS, "full-duplex"))) {
3937 		dp->full_duplex =
3938 		    usbgem_prop_get_int(dp, "full-duplex", 1) != 0;
3939 		dp->anadv_autoneg = B_FALSE;
3940 		if (dp->full_duplex) {
3941 			dp->anadv_1000hdx = B_FALSE;
3942 			dp->anadv_100hdx = B_FALSE;
3943 			dp->anadv_10hdx = B_FALSE;
3944 		} else {
3945 			dp->anadv_1000fdx = B_FALSE;
3946 			dp->anadv_100fdx = B_FALSE;
3947 			dp->anadv_10fdx = B_FALSE;
3948 		}
3949 	}
3950 
3951 	if ((val = usbgem_prop_get_int(dp, "speed", 0)) > 0) {
3952 		dp->anadv_autoneg = B_FALSE;
3953 		switch (val) {
3954 		case 1000:
3955 			dp->speed = USBGEM_SPD_1000;
3956 			dp->anadv_100t4 = B_FALSE;
3957 			dp->anadv_100fdx = B_FALSE;
3958 			dp->anadv_100hdx = B_FALSE;
3959 			dp->anadv_10fdx = B_FALSE;
3960 			dp->anadv_10hdx = B_FALSE;
3961 			break;
3962 		case 100:
3963 			dp->speed = USBGEM_SPD_100;
3964 			dp->anadv_1000fdx = B_FALSE;
3965 			dp->anadv_1000hdx = B_FALSE;
3966 			dp->anadv_10fdx = B_FALSE;
3967 			dp->anadv_10hdx = B_FALSE;
3968 			break;
3969 		case 10:
3970 			dp->speed = USBGEM_SPD_10;
3971 			dp->anadv_1000fdx = B_FALSE;
3972 			dp->anadv_1000hdx = B_FALSE;
3973 			dp->anadv_100t4 = B_FALSE;
3974 			dp->anadv_100fdx = B_FALSE;
3975 			dp->anadv_100hdx = B_FALSE;
3976 			break;
3977 		default:
3978 			cmn_err(CE_WARN,
3979 			    "!%s: property %s: illegal value:%d",
3980 			    dp->name, "speed", val);
3981 			dp->anadv_autoneg = B_TRUE;
3982 			break;
3983 		}
3984 	}
3985 	val = usbgem_prop_get_int(dp,
3986 	    "adv_pause", dp->ugc.usbgc_flow_control & 1);
3987 	val |= usbgem_prop_get_int(dp,
3988 	    "adv_asmpause", BOOLEAN(dp->ugc.usbgc_flow_control & 2)) << 1;
3989 	if (val > FLOW_CONTROL_RX_PAUSE || val < FLOW_CONTROL_NONE) {
3990 		cmn_err(CE_WARN,
3991 		    "!%s: property %s: illegal value:%d",
3992 		    dp->name, "flow-control", val);
3993 	} else {
3994 		val = min(val, dp->ugc.usbgc_flow_control);
3995 	}
3996 	dp->anadv_pause = BOOLEAN(val & 1);
3997 	dp->anadv_asmpause = BOOLEAN(val & 2);
3998 
3999 	dp->mtu = usbgem_prop_get_int(dp, "mtu", dp->mtu);
4000 	dp->txthr = usbgem_prop_get_int(dp, "txthr", dp->txthr);
4001 	dp->rxthr = usbgem_prop_get_int(dp, "rxthr", dp->rxthr);
4002 	dp->txmaxdma = usbgem_prop_get_int(dp, "txmaxdma", dp->txmaxdma);
4003 	dp->rxmaxdma = usbgem_prop_get_int(dp, "rxmaxdma", dp->rxmaxdma);
4004 #ifdef GEM_CONFIG_POLLING
4005 	dp->poll_pkt_delay =
4006 	    usbgem_prop_get_int(dp, "pkt_delay", dp->poll_pkt_delay);
4007 
4008 	dp->max_poll_interval[GEM_SPD_10] =
4009 	    usbgem_prop_get_int(dp, "max_poll_interval_10",
4010 	    dp->max_poll_interval[GEM_SPD_10]);
4011 	dp->max_poll_interval[GEM_SPD_100] =
4012 	    usbgem_prop_get_int(dp, "max_poll_interval_100",
4013 	    dp->max_poll_interval[GEM_SPD_100]);
4014 	dp->max_poll_interval[GEM_SPD_1000] =
4015 	    usbgem_prop_get_int(dp, "max_poll_interval_1000",
4016 	    dp->max_poll_interval[GEM_SPD_1000]);
4017 
4018 	dp->min_poll_interval[GEM_SPD_10] =
4019 	    usbgem_prop_get_int(dp, "min_poll_interval_10",
4020 	    dp->min_poll_interval[GEM_SPD_10]);
4021 	dp->min_poll_interval[GEM_SPD_100] =
4022 	    usbgem_prop_get_int(dp, "min_poll_interval_100",
4023 	    dp->min_poll_interval[GEM_SPD_100]);
4024 	dp->min_poll_interval[GEM_SPD_1000] =
4025 	    usbgem_prop_get_int(dp, "min_poll_interval_1000",
4026 	    dp->min_poll_interval[GEM_SPD_1000]);
4027 #endif
4028 }
4029 
4030 /*
4031  * usbem kstat support
4032  */
4033 #ifndef GEM_CONFIG_GLDv3
4034 /* kstat items based from dmfe driver */
4035 
4036 struct usbgem_kstat_named {
4037 	struct kstat_named	ks_xcvr_addr;
4038 	struct kstat_named	ks_xcvr_id;
4039 	struct kstat_named	ks_xcvr_inuse;
4040 	struct kstat_named	ks_link_up;
4041 	struct kstat_named	ks_link_duplex;	/* 0:unknwon, 1:half, 2:full */
4042 	struct kstat_named	ks_cap_1000fdx;
4043 	struct kstat_named	ks_cap_1000hdx;
4044 	struct kstat_named	ks_cap_100fdx;
4045 	struct kstat_named	ks_cap_100hdx;
4046 	struct kstat_named	ks_cap_10fdx;
4047 	struct kstat_named	ks_cap_10hdx;
4048 #ifdef NEVER
4049 	struct kstat_named	ks_cap_remfault;
4050 #endif
4051 	struct kstat_named	ks_cap_autoneg;
4052 
4053 	struct kstat_named	ks_adv_cap_1000fdx;
4054 	struct kstat_named	ks_adv_cap_1000hdx;
4055 	struct kstat_named	ks_adv_cap_100fdx;
4056 	struct kstat_named	ks_adv_cap_100hdx;
4057 	struct kstat_named	ks_adv_cap_10fdx;
4058 	struct kstat_named	ks_adv_cap_10hdx;
4059 #ifdef NEVER
4060 	struct kstat_named	ks_adv_cap_remfault;
4061 #endif
4062 	struct kstat_named	ks_adv_cap_autoneg;
4063 	struct kstat_named	ks_lp_cap_1000fdx;
4064 	struct kstat_named	ks_lp_cap_1000hdx;
4065 	struct kstat_named	ks_lp_cap_100fdx;
4066 	struct kstat_named	ks_lp_cap_100hdx;
4067 	struct kstat_named	ks_lp_cap_10fdx;
4068 	struct kstat_named	ks_lp_cap_10hdx;
4069 	struct kstat_named	ks_lp_cap_remfault;
4070 	struct kstat_named	ks_lp_cap_autoneg;
4071 };
4072 
4073 static int
4074 usbgem_kstat_update(kstat_t *ksp, int rw)
4075 {
4076 	struct usbgem_kstat_named *knp;
4077 	struct usbgem_dev *dp = (struct usbgem_dev *)ksp->ks_private;
4078 
4079 	if (rw != KSTAT_READ) {
4080 		return (0);
4081 	}
4082 
4083 	knp = (struct usbgem_kstat_named *)ksp->ks_data;
4084 
4085 	knp->ks_xcvr_addr.value.ul = dp->mii_phy_addr;
4086 	knp->ks_xcvr_id.value.ul = dp->mii_phy_id;
4087 	knp->ks_xcvr_inuse.value.ul = usbgem_mac_xcvr_inuse(dp);
4088 	knp->ks_link_up.value.ul = dp->mii_state == MII_STATE_LINKUP;
4089 	knp->ks_link_duplex.value.ul =
4090 	    (dp->mii_state == MII_STATE_LINKUP) ?
4091 	    (dp->full_duplex ? 2 : 1) : 0;
4092 
4093 	knp->ks_cap_1000fdx.value.ul =
4094 	    (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
4095 	    (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
4096 	knp->ks_cap_1000hdx.value.ul =
4097 	    (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
4098 	    (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
4099 	knp->ks_cap_100fdx.value.ul =
4100 	    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4101 	knp->ks_cap_100hdx.value.ul =
4102 	    BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4103 	knp->ks_cap_10fdx.value.ul =
4104 	    BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4105 	knp->ks_cap_10hdx.value.ul =
4106 	    BOOLEAN(dp->mii_status & MII_STATUS_10);
4107 #ifdef NEVER
4108 	knp->ks_cap_remfault.value.ul = B_TRUE;
4109 #endif
4110 	knp->ks_cap_autoneg.value.ul =
4111 	    BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4112 
4113 	knp->ks_adv_cap_1000fdx.value.ul = dp->anadv_1000fdx;
4114 	knp->ks_adv_cap_1000hdx.value.ul = dp->anadv_1000hdx;
4115 	knp->ks_adv_cap_100fdx.value.ul	= dp->anadv_100fdx;
4116 	knp->ks_adv_cap_100hdx.value.ul	= dp->anadv_100hdx;
4117 	knp->ks_adv_cap_10fdx.value.ul	= dp->anadv_10fdx;
4118 	knp->ks_adv_cap_10hdx.value.ul	= dp->anadv_10hdx;
4119 #ifdef NEVER
4120 	knp->ks_adv_cap_remfault.value.ul = 0;
4121 #endif
4122 	knp->ks_adv_cap_autoneg.value.ul = dp->anadv_autoneg;
4123 
4124 	knp->ks_lp_cap_1000fdx.value.ul =
4125 	    BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
4126 	knp->ks_lp_cap_1000hdx.value.ul =
4127 	    BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
4128 	knp->ks_lp_cap_100fdx.value.ul =
4129 	    BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
4130 	knp->ks_lp_cap_100hdx.value.ul =
4131 	    BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
4132 	knp->ks_lp_cap_10fdx.value.ul =
4133 	    BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
4134 	knp->ks_lp_cap_10hdx.value.ul =
4135 	    BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
4136 	knp->ks_lp_cap_remfault.value.ul =
4137 	    BOOLEAN(dp->mii_exp & MII_AN_EXP_PARFAULT);
4138 	knp->ks_lp_cap_autoneg.value.ul =
4139 	    BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
4140 
4141 	return (0);
4142 }
4143 
4144 
4145 static int
4146 usbgem_kstat_init(struct usbgem_dev *dp)
4147 {
4148 	int			i;
4149 	kstat_t			*ksp;
4150 	struct usbgem_kstat_named	*knp;
4151 
4152 	ksp = kstat_create(
4153 	    (char *)ddi_driver_name(dp->dip), ddi_get_instance(dp->dip),
4154 	    "mii", "net", KSTAT_TYPE_NAMED,
4155 	    sizeof (*knp) / sizeof (knp->ks_xcvr_addr), 0);
4156 
4157 	if (ksp == NULL) {
4158 		cmn_err(CE_WARN, "%s: %s() for mii failed",
4159 		    dp->name, __func__);
4160 		return (USB_FAILURE);
4161 	}
4162 
4163 	knp = (struct usbgem_kstat_named *)ksp->ks_data;
4164 
4165 	kstat_named_init(&knp->ks_xcvr_addr, "xcvr_addr",
4166 	    KSTAT_DATA_INT32);
4167 	kstat_named_init(&knp->ks_xcvr_id, "xcvr_id",
4168 	    KSTAT_DATA_UINT32);
4169 	kstat_named_init(&knp->ks_xcvr_inuse, "xcvr_inuse",
4170 	    KSTAT_DATA_UINT32);
4171 	kstat_named_init(&knp->ks_link_up, "link_up",
4172 	    KSTAT_DATA_UINT32);
4173 	kstat_named_init(&knp->ks_link_duplex, "link_duplex",
4174 	    KSTAT_DATA_UINT32);
4175 	kstat_named_init(&knp->ks_cap_1000fdx, "cap_1000fdx",
4176 	    KSTAT_DATA_UINT32);
4177 	kstat_named_init(&knp->ks_cap_1000hdx, "cap_1000hdx",
4178 	    KSTAT_DATA_UINT32);
4179 	kstat_named_init(&knp->ks_cap_100fdx, "cap_100fdx",
4180 	    KSTAT_DATA_UINT32);
4181 	kstat_named_init(&knp->ks_cap_100hdx, "cap_100hdx",
4182 	    KSTAT_DATA_UINT32);
4183 	kstat_named_init(&knp->ks_cap_10fdx, "cap_10fdx",
4184 	    KSTAT_DATA_UINT32);
4185 	kstat_named_init(&knp->ks_cap_10hdx, "cap_10hdx",
4186 	    KSTAT_DATA_UINT32);
4187 #ifdef NEVER
4188 	kstat_named_init(&knp->ks_cap_remfault, "cap_rem_fault",
4189 	    KSTAT_DATA_UINT32);
4190 #endif
4191 	kstat_named_init(&knp->ks_cap_autoneg, "cap_autoneg",
4192 	    KSTAT_DATA_UINT32);
4193 	kstat_named_init(&knp->ks_adv_cap_1000fdx, "adv_cap_1000fdx",
4194 	    KSTAT_DATA_UINT32);
4195 	kstat_named_init(&knp->ks_adv_cap_1000hdx, "adv_cap_1000hdx",
4196 	    KSTAT_DATA_UINT32);
4197 	kstat_named_init(&knp->ks_adv_cap_100fdx, "adv_cap_100fdx",
4198 	    KSTAT_DATA_UINT32);
4199 	kstat_named_init(&knp->ks_adv_cap_100hdx, "adv_cap_100hdx",
4200 	    KSTAT_DATA_UINT32);
4201 	kstat_named_init(&knp->ks_adv_cap_10fdx, "adv_cap_10fdx",
4202 	    KSTAT_DATA_UINT32);
4203 	kstat_named_init(&knp->ks_adv_cap_10hdx, "adv_cap_10hdx",
4204 	    KSTAT_DATA_UINT32);
4205 #ifdef NEVER
4206 	kstat_named_init(&knp->ks_adv_cap_remfault, "adv_rem_fault",
4207 	    KSTAT_DATA_UINT32);
4208 #endif
4209 	kstat_named_init(&knp->ks_adv_cap_autoneg, "adv_cap_autoneg",
4210 	    KSTAT_DATA_UINT32);
4211 
4212 	kstat_named_init(&knp->ks_lp_cap_1000fdx, "lp_cap_1000fdx",
4213 	    KSTAT_DATA_UINT32);
4214 	kstat_named_init(&knp->ks_lp_cap_1000hdx, "lp_cap_1000hdx",
4215 	    KSTAT_DATA_UINT32);
4216 	kstat_named_init(&knp->ks_lp_cap_100fdx, "lp_cap_100fdx",
4217 	    KSTAT_DATA_UINT32);
4218 	kstat_named_init(&knp->ks_lp_cap_100hdx, "lp_cap_100hdx",
4219 	    KSTAT_DATA_UINT32);
4220 	kstat_named_init(&knp->ks_lp_cap_10fdx, "lp_cap_10fdx",
4221 	    KSTAT_DATA_UINT32);
4222 	kstat_named_init(&knp->ks_lp_cap_10hdx, "lp_cap_10hdx",
4223 	    KSTAT_DATA_UINT32);
4224 	kstat_named_init(&knp->ks_lp_cap_remfault, "lp_cap_rem_fault",
4225 	    KSTAT_DATA_UINT32);
4226 	kstat_named_init(&knp->ks_lp_cap_autoneg, "lp_cap_autoneg",
4227 	    KSTAT_DATA_UINT32);
4228 
4229 	ksp->ks_private = (void *) dp;
4230 	ksp->ks_update = usbgem_kstat_update;
4231 	dp->ksp = ksp;
4232 
4233 	kstat_install(ksp);
4234 
4235 	return (USB_SUCCESS);
4236 }
4237 #endif /* GEM_CONFIG_GLDv3 */
4238 /* ======================================================================== */
4239 /*
4240  * attach/detatch/usb support
4241  */
4242 /* ======================================================================== */
4243 int
4244 usbgem_ctrl_out(struct usbgem_dev *dp,
4245     uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len,
4246     void *bp, int size)
4247 {
4248 	mblk_t			*data;
4249 	usb_ctrl_setup_t	setup;
4250 	usb_cr_t		completion_reason;
4251 	usb_cb_flags_t		cb_flags;
4252 	usb_flags_t		flags;
4253 	int			i;
4254 	int			ret;
4255 
4256 	DPRINTF(4, (CE_CONT, "!%s: %s "
4257 	    "reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x "
4258 	    "bp:0x%p nic_state:%d",
4259 	    dp->name, __func__, reqt, req, val, ix, len, bp, dp->nic_state));
4260 
4261 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
4262 		return (USB_PIPE_ERROR);
4263 	}
4264 
4265 	data = NULL;
4266 	if (size > 0) {
4267 		if ((data = allocb(size, 0)) == NULL) {
4268 			return (USB_FAILURE);
4269 		}
4270 
4271 		bcopy(bp, data->b_rptr, size);
4272 		data->b_wptr = data->b_rptr + size;
4273 	}
4274 
4275 	setup.bmRequestType = reqt;
4276 	setup.bRequest = req;
4277 	setup.wValue = val;
4278 	setup.wIndex = ix;
4279 	setup.wLength = len;
4280 	setup.attrs = 0;	/* attributes */
4281 
4282 	for (i = usbgem_ctrl_retry; i > 0; i--) {
4283 		completion_reason = 0;
4284 		cb_flags = 0;
4285 
4286 		ret = usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp),
4287 		    &setup, &data, &completion_reason, &cb_flags, 0);
4288 
4289 		if (ret == USB_SUCCESS) {
4290 			break;
4291 		}
4292 		if (i == 1) {
4293 			cmn_err(CE_WARN,
4294 			    "!%s: %s failed: "
4295 			    "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x "
4296 			    "ret:%d cr:%s(%d), cb_flags:0x%x %s",
4297 			    dp->name, __func__, reqt, req, val, ix, len,
4298 			    ret, usb_str_cr(completion_reason),
4299 			    completion_reason,
4300 			    cb_flags,
4301 			    (i > 1) ? "retrying..." : "fatal");
4302 		}
4303 	}
4304 
4305 	if (data != NULL) {
4306 		freemsg(data);
4307 	}
4308 
4309 	return (ret);
4310 }
4311 
4312 int
4313 usbgem_ctrl_in(struct usbgem_dev *dp,
4314     uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len,
4315     void *bp, int size)
4316 {
4317 	mblk_t			*data;
4318 	usb_ctrl_setup_t	setup;
4319 	usb_cr_t		completion_reason;
4320 	usb_cb_flags_t		cb_flags;
4321 	int			i;
4322 	int			ret;
4323 	int			reclen;
4324 
4325 	DPRINTF(4, (CE_CONT,
4326 	    "!%s: %s:"
4327 	    " reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x"
4328 	    " bp:x%p mac_state:%d",
4329 	    dp->name, __func__, reqt, req, val, ix, len, bp, dp->mac_state));
4330 
4331 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
4332 		return (USB_PIPE_ERROR);
4333 	}
4334 
4335 	data = NULL;
4336 
4337 	setup.bmRequestType = reqt;
4338 	setup.bRequest = req;
4339 	setup.wValue = val;
4340 	setup.wIndex = ix;
4341 	setup.wLength = len;
4342 	setup.attrs = USB_ATTRS_AUTOCLEARING;	/* XXX */
4343 
4344 	for (i = usbgem_ctrl_retry; i > 0; i--) {
4345 		completion_reason = 0;
4346 		cb_flags = 0;
4347 		ret = usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp), &setup, &data,
4348 		    &completion_reason, &cb_flags, 0);
4349 
4350 		if (ret == USB_SUCCESS) {
4351 			reclen = msgdsize(data);
4352 			bcopy(data->b_rptr, bp, min(reclen, size));
4353 			break;
4354 		}
4355 		if (i == 1) {
4356 			cmn_err(CE_WARN,
4357 			    "!%s: %s failed: "
4358 			    "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x "
4359 			    "ret:%d cr:%s(%d) cb_flags:0x%x %s",
4360 			    dp->name, __func__,
4361 			    reqt, req, val, ix, len,
4362 			    ret, usb_str_cr(completion_reason),
4363 			    completion_reason,
4364 			    cb_flags,
4365 			    (i > 1) ? "retrying..." : "fatal");
4366 		}
4367 	}
4368 
4369 	if (data) {
4370 		freemsg(data);
4371 	}
4372 
4373 	return (ret);
4374 }
4375 
4376 int
4377 usbgem_ctrl_out_val(struct usbgem_dev *dp,
4378     uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len,
4379     uint32_t v)
4380 {
4381 	uint8_t	buf[4];
4382 
4383 	/* convert to little endian from native byte order */
4384 	switch (len) {
4385 	case 4:
4386 		buf[3] = v >> 24;
4387 		buf[2] = v >> 16;
4388 		/* FALLTHROUGH */
4389 	case 2:
4390 		buf[1] = v >> 8;
4391 		/* FALLTHROUGH */
4392 	case 1:
4393 		buf[0] = v;
4394 	}
4395 
4396 	return (usbgem_ctrl_out(dp, reqt, req, val, ix, len, buf, len));
4397 }
4398 
4399 int
4400 usbgem_ctrl_in_val(struct usbgem_dev *dp,
4401     uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len,
4402     void *valp)
4403 {
4404 	uint8_t		buf[4];
4405 	uint_t		v;
4406 	int		err;
4407 
4408 #ifdef SANITY
4409 	bzero(buf, sizeof (buf));
4410 #endif
4411 	err = usbgem_ctrl_in(dp, reqt, req, val, ix, len, buf, len);
4412 	if (err == USB_SUCCESS) {
4413 		v = 0;
4414 		switch (len) {
4415 		case 4:
4416 			v |= buf[3] << 24;
4417 			v |= buf[2] << 16;
4418 			/* FALLTHROUGH */
4419 		case 2:
4420 			v |= buf[1] << 8;
4421 			/* FALLTHROUGH */
4422 		case 1:
4423 			v |= buf[0];
4424 		}
4425 
4426 		switch (len) {
4427 		case 4:
4428 			*(uint32_t *)valp = v;
4429 			break;
4430 		case 2:
4431 			*(uint16_t *)valp = v;
4432 			break;
4433 		case 1:
4434 			*(uint8_t *)valp = v;
4435 			break;
4436 		}
4437 	}
4438 	return (err);
4439 }
4440 
4441 /*
4442  * Attach / detach / disconnect / reconnect management
4443  */
4444 static int
4445 usbgem_open_pipes(struct usbgem_dev *dp)
4446 {
4447 	int			i;
4448 	int			ret;
4449 	int			ifnum;
4450 	int			alt;
4451 	usb_client_dev_data_t	*reg_data;
4452 	usb_ep_data_t		*ep_tree_node;
4453 
4454 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4455 
4456 	ifnum = dp->ugc.usbgc_ifnum;
4457 	alt = dp->ugc.usbgc_alt;
4458 
4459 	ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt,
4460 	    0, USB_EP_ATTR_BULK, USB_EP_DIR_IN);
4461 	if (ep_tree_node == NULL) {
4462 		cmn_err(CE_WARN, "!%s: %s: ep_bulkin is NULL",
4463 		    dp->name, __func__);
4464 		goto err;
4465 	}
4466 	dp->ep_bulkin = &ep_tree_node->ep_descr;
4467 
4468 	ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt,
4469 	    0, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
4470 	if (ep_tree_node == NULL) {
4471 		cmn_err(CE_WARN, "!%s: %s: ep_bulkout is NULL",
4472 		    dp->name, __func__);
4473 		goto err;
4474 	}
4475 	dp->ep_bulkout = &ep_tree_node->ep_descr;
4476 
4477 	ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt,
4478 	    0, USB_EP_ATTR_INTR, USB_EP_DIR_IN);
4479 	if (ep_tree_node) {
4480 		dp->ep_intr = &ep_tree_node->ep_descr;
4481 	} else {
4482 		/* don't care */
4483 		DPRINTF(1, (CE_CONT, "!%s: %s: ep_intr is NULL",
4484 		    dp->name, __func__));
4485 		dp->ep_intr = NULL;
4486 	}
4487 
4488 	/* XXX -- no need to open default pipe */
4489 
4490 	/* open bulk out pipe */
4491 	bzero(&dp->policy_bulkout, sizeof (usb_pipe_policy_t));
4492 	dp->policy_bulkout.pp_max_async_reqs = 1;
4493 
4494 	if ((ret = usb_pipe_open(dp->dip,
4495 	    dp->ep_bulkout, &dp->policy_bulkout, USB_FLAGS_SLEEP,
4496 	    &dp->bulkout_pipe)) != USB_SUCCESS) {
4497 		cmn_err(CE_WARN,
4498 		    "!%s: %s: err:%x: failed to open bulk-out pipe",
4499 		    dp->name, __func__, ret);
4500 		dp->bulkout_pipe = NULL;
4501 		goto err;
4502 	}
4503 	DPRINTF(1, (CE_CONT, "!%s: %s: bulkout_pipe opened successfully",
4504 	    dp->name, __func__));
4505 
4506 	/* open bulk in pipe */
4507 	bzero(&dp->policy_bulkin, sizeof (usb_pipe_policy_t));
4508 	dp->policy_bulkin.pp_max_async_reqs = 1;
4509 	if ((ret = usb_pipe_open(dp->dip,
4510 	    dp->ep_bulkin, &dp->policy_bulkin, USB_FLAGS_SLEEP,
4511 	    &dp->bulkin_pipe)) != USB_SUCCESS) {
4512 		cmn_err(CE_WARN,
4513 		    "!%s: %s: ret:%x failed to open bulk-in pipe",
4514 		    dp->name, __func__, ret);
4515 		dp->bulkin_pipe = NULL;
4516 		goto err;
4517 	}
4518 	DPRINTF(1, (CE_CONT, "!%s: %s: bulkin_pipe opened successfully",
4519 	    dp->name, __func__));
4520 
4521 	if (dp->ep_intr) {
4522 		/* open interrupt pipe */
4523 		bzero(&dp->policy_interrupt, sizeof (usb_pipe_policy_t));
4524 		dp->policy_interrupt.pp_max_async_reqs = 1;
4525 		if ((ret = usb_pipe_open(dp->dip, dp->ep_intr,
4526 		    &dp->policy_interrupt, USB_FLAGS_SLEEP,
4527 		    &dp->intr_pipe)) != USB_SUCCESS) {
4528 			cmn_err(CE_WARN,
4529 			    "!%s: %s: ret:%x failed to open interrupt pipe",
4530 			    dp->name, __func__, ret);
4531 			dp->intr_pipe = NULL;
4532 			goto err;
4533 		}
4534 	}
4535 	DPRINTF(1, (CE_CONT, "!%s: %s: intr_pipe opened successfully",
4536 	    dp->name, __func__));
4537 
4538 	return (USB_SUCCESS);
4539 
4540 err:
4541 	if (dp->bulkin_pipe) {
4542 		usb_pipe_close(dp->dip,
4543 		    dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0);
4544 		dp->bulkin_pipe = NULL;
4545 	}
4546 	if (dp->bulkout_pipe) {
4547 		usb_pipe_close(dp->dip,
4548 		    dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0);
4549 		dp->bulkout_pipe = NULL;
4550 	}
4551 	if (dp->intr_pipe) {
4552 		usb_pipe_close(dp->dip,
4553 		    dp->intr_pipe, USB_FLAGS_SLEEP, NULL, 0);
4554 		dp->intr_pipe = NULL;
4555 	}
4556 
4557 	return (USB_FAILURE);
4558 }
4559 
4560 static int
4561 usbgem_close_pipes(struct usbgem_dev *dp)
4562 {
4563 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4564 
4565 	if (dp->intr_pipe) {
4566 		usb_pipe_close(dp->dip,
4567 		    dp->intr_pipe, USB_FLAGS_SLEEP, NULL, 0);
4568 		dp->intr_pipe = NULL;
4569 	}
4570 	DPRINTF(1, (CE_CONT, "!%s: %s: 1", dp->name, __func__));
4571 
4572 	ASSERT(dp->bulkin_pipe);
4573 	usb_pipe_close(dp->dip, dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0);
4574 	dp->bulkin_pipe = NULL;
4575 	DPRINTF(1, (CE_CONT, "!%s: %s: 2", dp->name, __func__));
4576 
4577 	ASSERT(dp->bulkout_pipe);
4578 	usb_pipe_close(dp->dip, dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0);
4579 	dp->bulkout_pipe = NULL;
4580 	DPRINTF(1, (CE_CONT, "!%s: %s: 3", dp->name, __func__));
4581 
4582 	return (USB_SUCCESS);
4583 }
4584 
4585 #define	FREEZE_GRACEFUL		(B_TRUE)
4586 #define	FREEZE_NO_GRACEFUL	(B_FALSE)
4587 static int
4588 usbgem_freeze_device(struct usbgem_dev *dp, boolean_t graceful)
4589 {
4590 	DPRINTF(0, (CE_NOTE, "!%s: %s: called", dp->name, __func__));
4591 
4592 	/* stop nic activity */
4593 	(void) usbgem_mac_stop(dp, MAC_STATE_DISCONNECTED, graceful);
4594 
4595 	/*
4596 	 * Here we free all memory resource allocated, because it will
4597 	 * cause to panic the system that we free usb_bulk_req objects
4598 	 * during the usb device is disconnected.
4599 	 */
4600 	(void) usbgem_free_memory(dp);
4601 
4602 	return (USB_SUCCESS);
4603 }
4604 
4605 static int
4606 usbgem_disconnect_cb(dev_info_t *dip)
4607 {
4608 	int	ret;
4609 	struct usbgem_dev	*dp;
4610 
4611 	dp = USBGEM_GET_DEV(dip);
4612 
4613 	cmn_err(CE_NOTE, "!%s: the usb device was disconnected (dp=%p)",
4614 	    dp->name, (void *)dp);
4615 
4616 	/* start serialize */
4617 	rw_enter(&dp->dev_state_lock, RW_WRITER);
4618 
4619 	ret = usbgem_freeze_device(dp, 0);
4620 
4621 	/* end of serialize */
4622 	rw_exit(&dp->dev_state_lock);
4623 
4624 	return (ret);
4625 }
4626 
4627 static int
4628 usbgem_recover_device(struct usbgem_dev	*dp)
4629 {
4630 	int	err;
4631 
4632 	DPRINTF(0, (CE_NOTE, "!%s: %s: called", dp->name, __func__));
4633 
4634 	err = USB_SUCCESS;
4635 
4636 	/* reinitialize the usb connection */
4637 	usbgem_close_pipes(dp);
4638 	if ((err = usbgem_open_pipes(dp)) != USB_SUCCESS) {
4639 		goto x;
4640 	}
4641 
4642 	/* initialize nic state */
4643 	dp->mac_state = MAC_STATE_STOPPED;
4644 	dp->mii_state = MII_STATE_UNKNOWN;
4645 
4646 	/* allocate memory resources again */
4647 	if ((err = usbgem_alloc_memory(dp)) != USB_SUCCESS) {
4648 		goto x;
4649 	}
4650 
4651 	/* restart nic and recover state */
4652 	(void) usbgem_restart_nic(dp);
4653 
4654 	usbgem_mii_init(dp);
4655 
4656 	/* kick potentially stopped house keeping thread */
4657 	cv_signal(&dp->link_watcher_wait_cv);
4658 x:
4659 	return (err);
4660 }
4661 
4662 static int
4663 usbgem_reconnect_cb(dev_info_t *dip)
4664 {
4665 	int	err = USB_SUCCESS;
4666 	struct usbgem_dev	*dp;
4667 
4668 	dp = USBGEM_GET_DEV(dip);
4669 	DPRINTF(0, (CE_CONT, "!%s: dp=%p", ddi_get_name(dip), dp));
4670 #ifdef notdef
4671 	/* check device changes after disconnect */
4672 	if (usb_check_same_device(dp->dip, NULL, USB_LOG_L2, -1,
4673 	    USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
4674 		cmn_err(CE_CONT,
4675 		    "!%s: no or different device installed", dp->name);
4676 		return (DDI_SUCCESS);
4677 	}
4678 #endif
4679 	cmn_err(CE_NOTE, "%s: the usb device was reconnected", dp->name);
4680 
4681 	/* start serialize */
4682 	rw_enter(&dp->dev_state_lock, RW_WRITER);
4683 
4684 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
4685 		err = usbgem_recover_device(dp);
4686 	}
4687 
4688 	/* end of serialize */
4689 	rw_exit(&dp->dev_state_lock);
4690 
4691 	return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4692 }
4693 
4694 int
4695 usbgem_suspend(dev_info_t *dip)
4696 {
4697 	int	err = USB_SUCCESS;
4698 	struct usbgem_dev	*dp;
4699 
4700 	dp = USBGEM_GET_DEV(dip);
4701 
4702 	DPRINTF(0, (CE_CONT, "!%s: %s: callded", dp->name, __func__));
4703 
4704 	/* start serialize */
4705 	rw_enter(&dp->dev_state_lock, RW_WRITER);
4706 
4707 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
4708 		err = usbgem_freeze_device(dp, STOP_GRACEFUL);
4709 	}
4710 
4711 	/* end of serialize */
4712 	rw_exit(&dp->dev_state_lock);
4713 
4714 	return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4715 }
4716 
4717 int
4718 usbgem_resume(dev_info_t *dip)
4719 {
4720 	int	err = USB_SUCCESS;
4721 	struct usbgem_dev	*dp;
4722 
4723 	dp = USBGEM_GET_DEV(dip);
4724 
4725 	DPRINTF(0, (CE_CONT, "!%s: %s: callded", dp->name, __func__));
4726 #ifdef notdef
4727 	/* check device changes after disconnect */
4728 	if (usb_check_same_device(dp->dip, NULL, USB_LOG_L2, -1,
4729 	    USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
4730 		cmn_err(CE_CONT,
4731 		    "!%s: no or different device installed", dp->name);
4732 		return (DDI_SUCCESS);
4733 	}
4734 #endif
4735 	/* start serialize */
4736 	rw_enter(&dp->dev_state_lock, RW_WRITER);
4737 
4738 	if (dp->mac_state == MAC_STATE_DISCONNECTED) {
4739 		err = usbgem_recover_device(dp);
4740 	}
4741 
4742 	/* end of serialize */
4743 	rw_exit(&dp->dev_state_lock);
4744 
4745 	return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4746 }
4747 
4748 #define	USBGEM_LOCAL_DATA_SIZE(gc)	\
4749 	(sizeof (struct usbgem_dev) + USBGEM_MCALLOC)
4750 
4751 struct usbgem_dev *
4752 usbgem_do_attach(dev_info_t *dip,
4753     struct usbgem_conf *gc, void *lp, int lmsize)
4754 {
4755 	struct usbgem_dev	*dp;
4756 	int			i;
4757 	mac_register_t		*macp = NULL;
4758 	int			ret;
4759 	int			unit;
4760 	int			err;
4761 
4762 	unit = ddi_get_instance(dip);
4763 
4764 	DPRINTF(2, (CE_CONT, "!usbgem%d: %s: called", unit, __func__));
4765 
4766 	/*
4767 	 * Allocate soft data structure
4768 	 */
4769 	dp = kmem_zalloc(USBGEM_LOCAL_DATA_SIZE(gc), KM_SLEEP);
4770 	if (dp == NULL) {
4771 		return (NULL);
4772 	}
4773 
4774 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
4775 		cmn_err(CE_WARN, "!gem%d: %s: mac_alloc failed",
4776 		    unit, __func__);
4777 		return (NULL);
4778 	}
4779 
4780 	/* link to private area */
4781 	dp->private = lp;
4782 	dp->priv_size = lmsize;
4783 	dp->mc_list = (struct mcast_addr *)&dp[1];
4784 
4785 	dp->dip = dip;
4786 	bcopy(gc->usbgc_name, dp->name, USBGEM_NAME_LEN);
4787 
4788 	/*
4789 	 * register with usb service
4790 	 */
4791 	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
4792 		cmn_err(CE_WARN,
4793 		    "%s: %s: usb_client_attach failed",
4794 		    dp->name, __func__);
4795 		goto err_free_private;
4796 	}
4797 
4798 	if (usb_get_dev_data(dip, &dp->reg_data,
4799 	    USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) {
4800 		dp->reg_data = NULL;
4801 		goto err_unregister_client;
4802 	}
4803 #ifdef USBGEM_DEBUG_LEVEL
4804 	usb_print_descr_tree(dp->dip, dp->reg_data);
4805 #endif
4806 
4807 	if (usbgem_open_pipes(dp) != USB_SUCCESS) {
4808 		/* failed to open pipes */
4809 		cmn_err(CE_WARN, "!%s: %s: failed to open pipes",
4810 		    dp->name, __func__);
4811 		goto err_unregister_client;
4812 	}
4813 
4814 	/*
4815 	 * Initialize mutexs and condition variables
4816 	 */
4817 	mutex_init(&dp->rxlock, NULL, MUTEX_DRIVER, NULL);
4818 	mutex_init(&dp->txlock, NULL, MUTEX_DRIVER, NULL);
4819 	cv_init(&dp->rx_drain_cv, NULL, CV_DRIVER, NULL);
4820 	cv_init(&dp->tx_drain_cv, NULL, CV_DRIVER, NULL);
4821 	rw_init(&dp->dev_state_lock, NULL, RW_DRIVER, NULL);
4822 	mutex_init(&dp->link_watcher_lock, NULL, MUTEX_DRIVER, NULL);
4823 	cv_init(&dp->link_watcher_wait_cv, NULL, CV_DRIVER, NULL);
4824 	sema_init(&dp->hal_op_lock, 1, NULL, SEMA_DRIVER, NULL);
4825 	sema_init(&dp->rxfilter_lock, 1, NULL, SEMA_DRIVER, NULL);
4826 
4827 	/*
4828 	 * Initialize configuration
4829 	 */
4830 	dp->ugc = *gc;
4831 
4832 	dp->mtu = ETHERMTU;
4833 	dp->rxmode = 0;
4834 	dp->speed = USBGEM_SPD_10;	/* default is 10Mbps */
4835 	dp->full_duplex = B_FALSE;	/* default is half */
4836 	dp->flow_control = FLOW_CONTROL_NONE;
4837 
4838 	dp->nic_state = NIC_STATE_STOPPED;
4839 	dp->mac_state = MAC_STATE_STOPPED;
4840 	dp->mii_state = MII_STATE_UNKNOWN;
4841 
4842 	/* performance tuning parameters */
4843 	dp->txthr = ETHERMAX;		/* tx fifo threshoold */
4844 	dp->txmaxdma = 16*4;		/* tx max dma burst size */
4845 	dp->rxthr = 128;		/* rx fifo threshoold */
4846 	dp->rxmaxdma = 16*4;		/* rx max dma burst size */
4847 
4848 	/*
4849 	 * Get media mode infomation from .conf file
4850 	 */
4851 	usbgem_read_conf(dp);
4852 
4853 	/* rx_buf_len depend on MTU */
4854 	dp->rx_buf_len = MAXPKTBUF(dp) + dp->ugc.usbgc_rx_header_len;
4855 
4856 	/*
4857 	 * Reset the chip
4858 	 */
4859 	if (usbgem_hal_reset_chip(dp) != USB_SUCCESS) {
4860 		cmn_err(CE_WARN,
4861 		    "!%s: %s: failed to reset the usb device",
4862 		    dp->name, __func__);
4863 		goto err_destroy_locks;
4864 	}
4865 
4866 	/*
4867 	 * HW dependant paremeter initialization
4868 	 */
4869 	if (usbgem_hal_attach_chip(dp) != USB_SUCCESS) {
4870 		cmn_err(CE_WARN,
4871 		    "!%s: %s: failed to attach the usb device",
4872 		    dp->name, __func__);
4873 		goto err_destroy_locks;
4874 	}
4875 
4876 	/* allocate resources */
4877 	if (usbgem_alloc_memory(dp) != USB_SUCCESS) {
4878 		goto err_destroy_locks;
4879 	}
4880 
4881 	DPRINTF(0, (CE_CONT,
4882 	    "!%s: %02x:%02x:%02x:%02x:%02x:%02x",
4883 	    dp->name,
4884 	    dp->dev_addr.ether_addr_octet[0],
4885 	    dp->dev_addr.ether_addr_octet[1],
4886 	    dp->dev_addr.ether_addr_octet[2],
4887 	    dp->dev_addr.ether_addr_octet[3],
4888 	    dp->dev_addr.ether_addr_octet[4],
4889 	    dp->dev_addr.ether_addr_octet[5]));
4890 
4891 	/* copy mac address */
4892 	dp->cur_addr = dp->dev_addr;
4893 
4894 	/* pre-calculated tx timeout in second for performance */
4895 	dp->bulkout_timeout =
4896 	    dp->ugc.usbgc_tx_timeout / drv_usectohz(1000*1000);
4897 
4898 	usbgem_gld3_init(dp, macp);
4899 
4900 	/* Probe MII phy (scan phy) */
4901 	dp->mii_lpable = 0;
4902 	dp->mii_advert = 0;
4903 	dp->mii_exp = 0;
4904 	dp->mii_ctl1000 = 0;
4905 	dp->mii_stat1000 = 0;
4906 
4907 	dp->mii_status_ro = 0;
4908 	dp->mii_xstatus_ro = 0;
4909 
4910 	if (usbgem_mii_probe(dp) != USB_SUCCESS) {
4911 		cmn_err(CE_WARN, "!%s: %s: mii_probe failed",
4912 		    dp->name, __func__);
4913 		goto err_free_memory;
4914 	}
4915 
4916 	/* mask unsupported abilities */
4917 	dp->anadv_autoneg &= BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4918 	dp->anadv_1000fdx &=
4919 	    BOOLEAN(dp->mii_xstatus &
4920 	    (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD));
4921 	dp->anadv_1000hdx &=
4922 	    BOOLEAN(dp->mii_xstatus &
4923 	    (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET));
4924 	dp->anadv_100t4 &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
4925 	dp->anadv_100fdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4926 	dp->anadv_100hdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4927 	dp->anadv_10fdx &= BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4928 	dp->anadv_10hdx &= BOOLEAN(dp->mii_status & MII_STATUS_10);
4929 
4930 	if (usbgem_mii_init(dp) != USB_SUCCESS) {
4931 		cmn_err(CE_WARN, "!%s: %s: mii_init failed",
4932 		    dp->name, __func__);
4933 		goto err_free_memory;
4934 	}
4935 
4936 	/*
4937 	 * Add interrupt to system.
4938 	 */
4939 	if (ret = mac_register(macp, &dp->mh)) {
4940 		cmn_err(CE_WARN, "!%s: mac_register failed, error:%d",
4941 		    dp->name, ret);
4942 		goto err_release_stats;
4943 	}
4944 	mac_free(macp);
4945 	macp = NULL;
4946 
4947 	if (usb_register_hotplug_cbs(dip,
4948 	    usbgem_suspend, usbgem_resume) != USB_SUCCESS) {
4949 		cmn_err(CE_WARN,
4950 		    "!%s: %s: failed to register hotplug cbs",
4951 		    dp->name, __func__);
4952 		goto err_unregister_gld;
4953 	}
4954 
4955 	/* reset mii and start mii link watcher */
4956 	if (usbgem_mii_start(dp) != USB_SUCCESS) {
4957 		goto err_unregister_hotplug;
4958 	}
4959 
4960 	/* start tx watchdow watcher */
4961 	if (usbgem_tx_watcher_start(dp)) {
4962 		goto err_usbgem_mii_stop;
4963 	}
4964 
4965 	ddi_set_driver_private(dip, (caddr_t)dp);
4966 
4967 	DPRINTF(2, (CE_CONT, "!%s: %s: return: success", dp->name, __func__));
4968 
4969 	return (dp);
4970 
4971 err_usbgem_mii_stop:
4972 	usbgem_mii_stop(dp);
4973 
4974 err_unregister_hotplug:
4975 	usb_unregister_hotplug_cbs(dip);
4976 
4977 err_unregister_gld:
4978 	mac_unregister(dp->mh);
4979 
4980 err_release_stats:
4981 err_free_memory:
4982 	usbgem_free_memory(dp);
4983 
4984 err_destroy_locks:
4985 	cv_destroy(&dp->tx_drain_cv);
4986 	cv_destroy(&dp->rx_drain_cv);
4987 	mutex_destroy(&dp->txlock);
4988 	mutex_destroy(&dp->rxlock);
4989 	rw_destroy(&dp->dev_state_lock);
4990 	mutex_destroy(&dp->link_watcher_lock);
4991 	cv_destroy(&dp->link_watcher_wait_cv);
4992 	sema_destroy(&dp->hal_op_lock);
4993 	sema_destroy(&dp->rxfilter_lock);
4994 
4995 err_close_pipes:
4996 	(void) usbgem_close_pipes(dp);
4997 
4998 err_unregister_client:
4999 	usb_client_detach(dp->dip, dp->reg_data);
5000 
5001 err_free_private:
5002 	if (macp) {
5003 		mac_free(macp);
5004 	}
5005 
5006 	kmem_free((caddr_t)dp, USBGEM_LOCAL_DATA_SIZE(gc));
5007 
5008 	return (NULL);
5009 }
5010 
5011 int
5012 usbgem_do_detach(dev_info_t *dip)
5013 {
5014 	struct usbgem_dev	*dp;
5015 
5016 	dp = USBGEM_GET_DEV(dip);
5017 
5018 	/* unregister with gld v3 */
5019 	if (mac_unregister(dp->mh) != DDI_SUCCESS) {
5020 		return (DDI_FAILURE);
5021 	}
5022 
5023 	/* unregister with hotplug service */
5024 	usb_unregister_hotplug_cbs(dip);
5025 
5026 	/* stop tx watchdog watcher */
5027 	usbgem_tx_watcher_stop(dp);
5028 
5029 	/* stop the link manager */
5030 	usbgem_mii_stop(dp);
5031 
5032 	/* unregister with usb service */
5033 	(void) usbgem_free_memory(dp);
5034 	(void) usbgem_close_pipes(dp);
5035 	usb_client_detach(dp->dip, dp->reg_data);
5036 	dp->reg_data = NULL;
5037 
5038 	/* release locks and condition variables */
5039 	mutex_destroy(&dp->txlock);
5040 	mutex_destroy(&dp->rxlock);
5041 	cv_destroy(&dp->tx_drain_cv);
5042 	cv_destroy(&dp->rx_drain_cv);
5043 	rw_destroy(&dp->dev_state_lock);
5044 	mutex_destroy(&dp->link_watcher_lock);
5045 	cv_destroy(&dp->link_watcher_wait_cv);
5046 	sema_destroy(&dp->hal_op_lock);
5047 	sema_destroy(&dp->rxfilter_lock);
5048 
5049 	/* release basic memory resources */
5050 	kmem_free((caddr_t)(dp->private), dp->priv_size);
5051 	kmem_free((caddr_t)dp, USBGEM_LOCAL_DATA_SIZE(&dp->ugc));
5052 
5053 	DPRINTF(2, (CE_CONT, "!%s: %s: return: success",
5054 	    ddi_driver_name(dip), __func__));
5055 
5056 	return (DDI_SUCCESS);
5057 }
5058 
5059 int
5060 usbgem_mod_init(struct dev_ops *dop, char *name)
5061 {
5062 	major_t	major;
5063 	major = ddi_name_to_major(name);
5064 	if (major == DDI_MAJOR_T_NONE) {
5065 		return (DDI_FAILURE);
5066 	}
5067 	mac_init_ops(dop, name);
5068 
5069 	return (DDI_SUCCESS);
5070 }
5071 
5072 void
5073 usbgem_mod_fini(struct dev_ops *dop)
5074 {
5075 	mac_fini_ops(dop);
5076 }
5077 
5078 int
5079 usbgem_quiesce(dev_info_t *dip)
5080 {
5081 	struct usbgem_dev	*dp;
5082 
5083 	dp = USBGEM_GET_DEV(dip);
5084 
5085 	ASSERT(dp != NULL);
5086 
5087 	if (dp->mac_state != MAC_STATE_DISCONNECTED &&
5088 	    dp->mac_state != MAC_STATE_STOPPED) {
5089 		if (usbgem_hal_stop_chip(dp) != USB_SUCCESS) {
5090 			(void) usbgem_hal_reset_chip(dp);
5091 		}
5092 	}
5093 
5094 	/* devo_quiesce() must return DDI_SUCCESS always */
5095 	return (DDI_SUCCESS);
5096 }
5097