xref: /titanic_51/usr/src/uts/common/io/sfe/sfe_util.c (revision 80e2ca8596e3435bc3b76f3c597833ea0a87f85e)
1 /*
2  * sfe_util.c: general ethernet mac driver framework version 2.6
3  *
4  * Copyright (c) 2002-2008 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 2010 Sun Microsystems, Inc.  All rights reserved.
36  * Use is subject to license terms.
37  */
38 
39 /*
40  * System Header files.
41  */
42 #include <sys/types.h>
43 #include <sys/conf.h>
44 #include <sys/debug.h>
45 #include <sys/kmem.h>
46 #include <sys/vtrace.h>
47 #include <sys/ethernet.h>
48 #include <sys/modctl.h>
49 #include <sys/errno.h>
50 #include <sys/ddi.h>
51 #include <sys/sunddi.h>
52 #include <sys/stream.h>		/* required for MBLK* */
53 #include <sys/strsun.h>		/* required for mionack() */
54 #include <sys/byteorder.h>
55 #include <sys/pci.h>
56 #include <inet/common.h>
57 #include <inet/led.h>
58 #include <inet/mi.h>
59 #include <inet/nd.h>
60 #include <sys/crc32.h>
61 
62 #include <sys/note.h>
63 
64 #include "sfe_mii.h"
65 #include "sfe_util.h"
66 
67 
68 
69 extern char ident[];
70 
71 /* Debugging support */
72 #ifdef GEM_DEBUG_LEVEL
73 static int gem_debug = GEM_DEBUG_LEVEL;
74 #define	DPRINTF(n, args)	if (gem_debug > (n)) cmn_err args
75 #else
76 #define	DPRINTF(n, args)
77 #undef ASSERT
78 #define	ASSERT(x)
79 #endif
80 
81 #define	IOC_LINESIZE	0x40	/* Is it right for amd64? */
82 
83 /*
84  * Useful macros and typedefs
85  */
86 #define	ROUNDUP(x, a)	(((x) + (a) - 1) & ~((a) - 1))
87 
88 #define	GET_NET16(p)	((((uint8_t *)(p))[0] << 8)| ((uint8_t *)(p))[1])
89 #define	GET_ETHERTYPE(p)	GET_NET16(((uint8_t *)(p)) + ETHERADDRL*2)
90 
91 #define	GET_IPTYPEv4(p)	(((uint8_t *)(p))[sizeof (struct ether_header) + 9])
92 #define	GET_IPTYPEv6(p)	(((uint8_t *)(p))[sizeof (struct ether_header) + 6])
93 
94 
95 #ifndef INT32_MAX
96 #define	INT32_MAX	0x7fffffff
97 #endif
98 
99 #define	VTAG_OFF	(ETHERADDRL*2)
100 #ifndef VTAG_SIZE
101 #define	VTAG_SIZE	4
102 #endif
103 #ifndef VTAG_TPID
104 #define	VTAG_TPID	0x8100U
105 #endif
106 
107 #define	GET_TXBUF(dp, sn)	\
108 	&(dp)->tx_buf[SLOT((dp)->tx_slots_base + (sn), (dp)->gc.gc_tx_buf_size)]
109 
110 #ifndef offsetof
111 #define	offsetof(t, m)	((long)&(((t *) 0)->m))
112 #endif
113 #define	TXFLAG_VTAG(flag)	\
114 	(((flag) & GEM_TXFLAG_VTAG) >> GEM_TXFLAG_VTAG_SHIFT)
115 
116 #define	MAXPKTBUF(dp)	\
117 	((dp)->mtu + sizeof (struct ether_header) + VTAG_SIZE + ETHERFCSL)
118 
119 #define	WATCH_INTERVAL_FAST	drv_usectohz(100*1000)	/* 100mS */
120 #define	BOOLEAN(x)	((x) != 0)
121 
122 /*
123  * Macros to distinct chip generation.
124  */
125 
126 /*
127  * Private functions
128  */
129 static void gem_mii_start(struct gem_dev *);
130 static void gem_mii_stop(struct gem_dev *);
131 
132 /* local buffer management */
133 static void gem_nd_setup(struct gem_dev *dp);
134 static void gem_nd_cleanup(struct gem_dev *dp);
135 static int gem_alloc_memory(struct gem_dev *);
136 static void gem_free_memory(struct gem_dev *);
137 static void gem_init_rx_ring(struct gem_dev *);
138 static void gem_init_tx_ring(struct gem_dev *);
139 __INLINE__ static void gem_append_rxbuf(struct gem_dev *, struct rxbuf *);
140 
141 static void gem_tx_timeout(struct gem_dev *);
142 static void gem_mii_link_watcher(struct gem_dev *dp);
143 static int gem_mac_init(struct gem_dev *dp);
144 static int gem_mac_start(struct gem_dev *dp);
145 static int gem_mac_stop(struct gem_dev *dp, uint_t flags);
146 static void gem_mac_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp);
147 
148 static	struct ether_addr	gem_etherbroadcastaddr = {
149 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
150 };
151 
152 int gem_speed_value[] = {10, 100, 1000};
153 
154 /* ============================================================== */
155 /*
156  * Misc runtime routines
157  */
158 /* ============================================================== */
159 /*
160  * Ether CRC calculation according to 21143 data sheet
161  */
162 uint32_t
163 gem_ether_crc_le(const uint8_t *addr, int len)
164 {
165 	uint32_t	crc;
166 
167 	CRC32(crc, addr, ETHERADDRL, 0xffffffffU, crc32_table);
168 	return (crc);
169 }
170 
171 uint32_t
172 gem_ether_crc_be(const uint8_t *addr, int len)
173 {
174 	int		idx;
175 	int		bit;
176 	uint_t		data;
177 	uint32_t	crc;
178 #define	CRC32_POLY_BE	0x04c11db7
179 
180 	crc = 0xffffffff;
181 	for (idx = 0; idx < len; idx++) {
182 		for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
183 			crc = (crc << 1)
184 			    ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0);
185 		}
186 	}
187 	return (crc);
188 #undef	CRC32_POLY_BE
189 }
190 
191 int
192 gem_prop_get_int(struct gem_dev *dp, char *prop_template, int def_val)
193 {
194 	char	propname[32];
195 
196 	(void) sprintf(propname, prop_template, dp->name);
197 
198 	return (ddi_prop_get_int(DDI_DEV_T_ANY, dp->dip,
199 	    DDI_PROP_DONTPASS, propname, def_val));
200 }
201 
202 static int
203 gem_population(uint32_t x)
204 {
205 	int	i;
206 	int	cnt;
207 
208 	cnt = 0;
209 	for (i = 0; i < 32; i++) {
210 		if (x & (1 << i)) {
211 			cnt++;
212 		}
213 	}
214 	return (cnt);
215 }
216 
217 #ifdef GEM_DEBUG_LEVEL
218 #ifdef GEM_DEBUG_VLAN
219 static void
220 gem_dump_packet(struct gem_dev *dp, char *title, mblk_t *mp,
221     boolean_t check_cksum)
222 {
223 	char	msg[180];
224 	uint8_t	buf[18+20+20];
225 	uint8_t	*p;
226 	size_t	offset;
227 	uint_t	ethertype;
228 	uint_t	proto;
229 	uint_t	ipproto = 0;
230 	uint_t	iplen;
231 	uint_t	iphlen;
232 	uint_t	tcplen;
233 	uint_t	udplen;
234 	uint_t	cksum;
235 	int	rest;
236 	int	len;
237 	char	*bp;
238 	mblk_t	*tp;
239 	extern uint_t	ip_cksum(mblk_t *, int, uint32_t);
240 
241 	msg[0] = 0;
242 	bp = msg;
243 
244 	rest = sizeof (buf);
245 	offset = 0;
246 	for (tp = mp; tp; tp = tp->b_cont) {
247 		len = tp->b_wptr - tp->b_rptr;
248 		len = min(rest, len);
249 		bcopy(tp->b_rptr, &buf[offset], len);
250 		rest -= len;
251 		offset += len;
252 		if (rest == 0) {
253 			break;
254 		}
255 	}
256 
257 	offset = 0;
258 	p = &buf[offset];
259 
260 	/* ethernet address */
261 	sprintf(bp,
262 	    "ether: %02x:%02x:%02x:%02x:%02x:%02x"
263 	    " -> %02x:%02x:%02x:%02x:%02x:%02x",
264 	    p[6], p[7], p[8], p[9], p[10], p[11],
265 	    p[0], p[1], p[2], p[3], p[4], p[5]);
266 	bp = &msg[strlen(msg)];
267 
268 	/* vlag tag and etherrtype */
269 	ethertype = GET_ETHERTYPE(p);
270 	if (ethertype == VTAG_TPID) {
271 		sprintf(bp, " vtag:0x%04x", GET_NET16(&p[14]));
272 		bp = &msg[strlen(msg)];
273 
274 		offset += VTAG_SIZE;
275 		p = &buf[offset];
276 		ethertype = GET_ETHERTYPE(p);
277 	}
278 	sprintf(bp, " type:%04x", ethertype);
279 	bp = &msg[strlen(msg)];
280 
281 	/* ethernet packet length */
282 	sprintf(bp, " mblklen:%d", msgdsize(mp));
283 	bp = &msg[strlen(msg)];
284 	if (mp->b_cont) {
285 		sprintf(bp, "(");
286 		bp = &msg[strlen(msg)];
287 		for (tp = mp; tp; tp = tp->b_cont) {
288 			if (tp == mp) {
289 				sprintf(bp, "%d", tp->b_wptr - tp->b_rptr);
290 			} else {
291 				sprintf(bp, "+%d", tp->b_wptr - tp->b_rptr);
292 			}
293 			bp = &msg[strlen(msg)];
294 		}
295 		sprintf(bp, ")");
296 		bp = &msg[strlen(msg)];
297 	}
298 
299 	if (ethertype != ETHERTYPE_IP) {
300 		goto x;
301 	}
302 
303 	/* ip address */
304 	offset += sizeof (struct ether_header);
305 	p = &buf[offset];
306 	ipproto = p[9];
307 	iplen = GET_NET16(&p[2]);
308 	sprintf(bp, ", ip: %d.%d.%d.%d -> %d.%d.%d.%d proto:%d iplen:%d",
309 	    p[12], p[13], p[14], p[15],
310 	    p[16], p[17], p[18], p[19],
311 	    ipproto, iplen);
312 	bp = (void *)&msg[strlen(msg)];
313 
314 	iphlen = (p[0] & 0xf) * 4;
315 
316 	/* cksum for psuedo header */
317 	cksum = *(uint16_t *)&p[12];
318 	cksum += *(uint16_t *)&p[14];
319 	cksum += *(uint16_t *)&p[16];
320 	cksum += *(uint16_t *)&p[18];
321 	cksum += BE_16(ipproto);
322 
323 	/* tcp or udp protocol header */
324 	offset += iphlen;
325 	p = &buf[offset];
326 	if (ipproto == IPPROTO_TCP) {
327 		tcplen = iplen - iphlen;
328 		sprintf(bp, ", tcp: len:%d cksum:%x",
329 		    tcplen, GET_NET16(&p[16]));
330 		bp = (void *)&msg[strlen(msg)];
331 
332 		if (check_cksum) {
333 			cksum += BE_16(tcplen);
334 			cksum = (uint16_t)ip_cksum(mp, offset, cksum);
335 			sprintf(bp, " (%s)",
336 			    (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
337 			bp = (void *)&msg[strlen(msg)];
338 		}
339 	} else if (ipproto == IPPROTO_UDP) {
340 		udplen = GET_NET16(&p[4]);
341 		sprintf(bp, ", udp: len:%d cksum:%x",
342 		    udplen, GET_NET16(&p[6]));
343 		bp = (void *)&msg[strlen(msg)];
344 
345 		if (GET_NET16(&p[6]) && check_cksum) {
346 			cksum += *(uint16_t *)&p[4];
347 			cksum = (uint16_t)ip_cksum(mp, offset, cksum);
348 			sprintf(bp, " (%s)",
349 			    (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
350 			bp = (void *)&msg[strlen(msg)];
351 		}
352 	}
353 x:
354 	cmn_err(CE_CONT, "!%s: %s: %s", dp->name, title, msg);
355 }
356 #endif /* GEM_DEBUG_VLAN */
357 #endif /* GEM_DEBUG_LEVEL */
358 
359 /* ============================================================== */
360 /*
361  * IO cache flush
362  */
363 /* ============================================================== */
364 __INLINE__ void
365 gem_rx_desc_dma_sync(struct gem_dev *dp, int head, int nslot, int how)
366 {
367 	int	n;
368 	int	m;
369 	int	rx_desc_unit_shift = dp->gc.gc_rx_desc_unit_shift;
370 
371 	/* sync active descriptors */
372 	if (rx_desc_unit_shift < 0 || nslot == 0) {
373 		/* no rx descriptor ring */
374 		return;
375 	}
376 
377 	n = dp->gc.gc_rx_ring_size - head;
378 	if ((m = nslot - n) > 0) {
379 		(void) ddi_dma_sync(dp->desc_dma_handle,
380 		    (off_t)0,
381 		    (size_t)(m << rx_desc_unit_shift),
382 		    how);
383 		nslot = n;
384 	}
385 
386 	(void) ddi_dma_sync(dp->desc_dma_handle,
387 	    (off_t)(head << rx_desc_unit_shift),
388 	    (size_t)(nslot << rx_desc_unit_shift),
389 	    how);
390 }
391 
392 __INLINE__ void
393 gem_tx_desc_dma_sync(struct gem_dev *dp, int head, int nslot, int how)
394 {
395 	int	n;
396 	int	m;
397 	int	tx_desc_unit_shift = dp->gc.gc_tx_desc_unit_shift;
398 
399 	/* sync active descriptors */
400 	if (tx_desc_unit_shift < 0 || nslot == 0) {
401 		/* no tx descriptor ring */
402 		return;
403 	}
404 
405 	n = dp->gc.gc_tx_ring_size - head;
406 	if ((m = nslot - n) > 0) {
407 		(void) ddi_dma_sync(dp->desc_dma_handle,
408 		    (off_t)(dp->tx_ring_dma - dp->rx_ring_dma),
409 		    (size_t)(m << tx_desc_unit_shift),
410 		    how);
411 		nslot = n;
412 	}
413 
414 	(void) ddi_dma_sync(dp->desc_dma_handle,
415 	    (off_t)((head << tx_desc_unit_shift)
416 	    + (dp->tx_ring_dma - dp->rx_ring_dma)),
417 	    (size_t)(nslot << tx_desc_unit_shift),
418 	    how);
419 }
420 
421 static void
422 gem_rx_start_default(struct gem_dev *dp, int head, int nslot)
423 {
424 	gem_rx_desc_dma_sync(dp,
425 	    SLOT(head, dp->gc.gc_rx_ring_size), nslot,
426 	    DDI_DMA_SYNC_FORDEV);
427 }
428 
429 /* ============================================================== */
430 /*
431  * Buffer management
432  */
433 /* ============================================================== */
434 static void
435 gem_dump_txbuf(struct gem_dev *dp, int level, const char *title)
436 {
437 	cmn_err(level,
438 	    "!%s: %s: tx_active: %d[%d] %d[%d] (+%d), "
439 	    "tx_softq: %d[%d] %d[%d] (+%d), "
440 	    "tx_free: %d[%d] %d[%d] (+%d), "
441 	    "tx_desc: %d[%d] %d[%d] (+%d), "
442 	    "intr: %d[%d] (+%d), ",
443 	    dp->name, title,
444 	    dp->tx_active_head,
445 	    SLOT(dp->tx_active_head, dp->gc.gc_tx_buf_size),
446 	    dp->tx_active_tail,
447 	    SLOT(dp->tx_active_tail, dp->gc.gc_tx_buf_size),
448 	    dp->tx_active_tail - dp->tx_active_head,
449 	    dp->tx_softq_head,
450 	    SLOT(dp->tx_softq_head, dp->gc.gc_tx_buf_size),
451 	    dp->tx_softq_tail,
452 	    SLOT(dp->tx_softq_tail, dp->gc.gc_tx_buf_size),
453 	    dp->tx_softq_tail - dp->tx_softq_head,
454 	    dp->tx_free_head,
455 	    SLOT(dp->tx_free_head, dp->gc.gc_tx_buf_size),
456 	    dp->tx_free_tail,
457 	    SLOT(dp->tx_free_tail, dp->gc.gc_tx_buf_size),
458 	    dp->tx_free_tail - dp->tx_free_head,
459 	    dp->tx_desc_head,
460 	    SLOT(dp->tx_desc_head, dp->gc.gc_tx_ring_size),
461 	    dp->tx_desc_tail,
462 	    SLOT(dp->tx_desc_tail, dp->gc.gc_tx_ring_size),
463 	    dp->tx_desc_tail - dp->tx_desc_head,
464 	    dp->tx_desc_intr,
465 	    SLOT(dp->tx_desc_intr, dp->gc.gc_tx_ring_size),
466 	    dp->tx_desc_intr - dp->tx_desc_head);
467 }
468 
469 static void
470 gem_free_rxbuf(struct rxbuf *rbp)
471 {
472 	struct gem_dev	*dp;
473 
474 	dp = rbp->rxb_devp;
475 	ASSERT(mutex_owned(&dp->intrlock));
476 	rbp->rxb_next = dp->rx_buf_freelist;
477 	dp->rx_buf_freelist = rbp;
478 	dp->rx_buf_freecnt++;
479 }
480 
481 /*
482  * gem_get_rxbuf: supply a receive buffer which have been mapped into
483  * DMA space.
484  */
485 struct rxbuf *
486 gem_get_rxbuf(struct gem_dev *dp, int cansleep)
487 {
488 	struct rxbuf		*rbp;
489 	uint_t			count = 0;
490 	int			i;
491 	int			err;
492 
493 	ASSERT(mutex_owned(&dp->intrlock));
494 
495 	DPRINTF(3, (CE_CONT, "!gem_get_rxbuf: called freecnt:%d",
496 	    dp->rx_buf_freecnt));
497 	/*
498 	 * Get rx buffer management structure
499 	 */
500 	rbp = dp->rx_buf_freelist;
501 	if (rbp) {
502 		/* get one from the recycle list */
503 		ASSERT(dp->rx_buf_freecnt > 0);
504 
505 		dp->rx_buf_freelist = rbp->rxb_next;
506 		dp->rx_buf_freecnt--;
507 		rbp->rxb_next = NULL;
508 		return (rbp);
509 	}
510 
511 	/*
512 	 * Allocate a rx buffer management structure
513 	 */
514 	rbp = kmem_zalloc(sizeof (*rbp), cansleep ? KM_SLEEP : KM_NOSLEEP);
515 	if (rbp == NULL) {
516 		/* no memory */
517 		return (NULL);
518 	}
519 
520 	/*
521 	 * Prepare a back pointer to the device structure which will be
522 	 * refered on freeing the buffer later.
523 	 */
524 	rbp->rxb_devp = dp;
525 
526 	/* allocate a dma handle for rx data buffer */
527 	if ((err = ddi_dma_alloc_handle(dp->dip,
528 	    &dp->gc.gc_dma_attr_rxbuf,
529 	    (cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT),
530 	    NULL, &rbp->rxb_dh)) != DDI_SUCCESS) {
531 
532 		cmn_err(CE_WARN,
533 		    "!%s: %s: ddi_dma_alloc_handle:1 failed, err=%d",
534 		    dp->name, __func__, err);
535 
536 		kmem_free(rbp, sizeof (struct rxbuf));
537 		return (NULL);
538 	}
539 
540 	/* allocate a bounce buffer for rx */
541 	if ((err = ddi_dma_mem_alloc(rbp->rxb_dh,
542 	    ROUNDUP(dp->rx_buf_len, IOC_LINESIZE),
543 	    &dp->gc.gc_buf_attr,
544 		/*
545 		 * if the nic requires a header at the top of receive buffers,
546 		 * it may access the rx buffer randomly.
547 		 */
548 	    (dp->gc.gc_rx_header_len > 0)
549 	    ? DDI_DMA_CONSISTENT : DDI_DMA_STREAMING,
550 	    cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
551 	    NULL,
552 	    &rbp->rxb_buf, &rbp->rxb_buf_len,
553 	    &rbp->rxb_bah)) != DDI_SUCCESS) {
554 
555 		cmn_err(CE_WARN,
556 		    "!%s: %s: ddi_dma_mem_alloc: failed, err=%d",
557 		    dp->name, __func__, err);
558 
559 		ddi_dma_free_handle(&rbp->rxb_dh);
560 		kmem_free(rbp, sizeof (struct rxbuf));
561 		return (NULL);
562 	}
563 
564 	/* Mapin the bounce buffer into the DMA space */
565 	if ((err = ddi_dma_addr_bind_handle(rbp->rxb_dh,
566 	    NULL, rbp->rxb_buf, dp->rx_buf_len,
567 	    ((dp->gc.gc_rx_header_len > 0)
568 	    ?(DDI_DMA_RDWR | DDI_DMA_CONSISTENT)
569 	    :(DDI_DMA_READ | DDI_DMA_STREAMING)),
570 	    cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
571 	    NULL,
572 	    rbp->rxb_dmacookie,
573 	    &count)) != DDI_DMA_MAPPED) {
574 
575 		ASSERT(err != DDI_DMA_INUSE);
576 		DPRINTF(0, (CE_WARN,
577 		    "!%s: ddi_dma_addr_bind_handle: failed, err=%d",
578 		    dp->name, __func__, err));
579 
580 		/*
581 		 * we failed to allocate a dma resource
582 		 * for the rx bounce buffer.
583 		 */
584 		ddi_dma_mem_free(&rbp->rxb_bah);
585 		ddi_dma_free_handle(&rbp->rxb_dh);
586 		kmem_free(rbp, sizeof (struct rxbuf));
587 		return (NULL);
588 	}
589 
590 	/* correct the rest of the DMA mapping */
591 	for (i = 1; i < count; i++) {
592 		ddi_dma_nextcookie(rbp->rxb_dh, &rbp->rxb_dmacookie[i]);
593 	}
594 	rbp->rxb_nfrags = count;
595 
596 	/* Now we successfully prepared an rx buffer */
597 	dp->rx_buf_allocated++;
598 
599 	return (rbp);
600 }
601 
602 /* ============================================================== */
603 /*
604  * memory resource management
605  */
606 /* ============================================================== */
607 static int
608 gem_alloc_memory(struct gem_dev *dp)
609 {
610 	caddr_t			ring;
611 	caddr_t			buf;
612 	size_t			req_size;
613 	size_t			ring_len;
614 	size_t			buf_len;
615 	ddi_dma_cookie_t	ring_cookie;
616 	ddi_dma_cookie_t	buf_cookie;
617 	uint_t			count;
618 	int			i;
619 	int			err;
620 	struct txbuf		*tbp;
621 	int			tx_buf_len;
622 	ddi_dma_attr_t		dma_attr_txbounce;
623 
624 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
625 
626 	dp->desc_dma_handle = NULL;
627 	req_size = dp->rx_desc_size + dp->tx_desc_size + dp->gc.gc_io_area_size;
628 
629 	if (req_size > 0) {
630 		/*
631 		 * Alloc RX/TX descriptors and a io area.
632 		 */
633 		if ((err = ddi_dma_alloc_handle(dp->dip,
634 		    &dp->gc.gc_dma_attr_desc,
635 		    DDI_DMA_SLEEP, NULL,
636 		    &dp->desc_dma_handle)) != DDI_SUCCESS) {
637 			cmn_err(CE_WARN,
638 			    "!%s: %s: ddi_dma_alloc_handle failed: %d",
639 			    dp->name, __func__, err);
640 			return (ENOMEM);
641 		}
642 
643 		if ((err = ddi_dma_mem_alloc(dp->desc_dma_handle,
644 		    req_size, &dp->gc.gc_desc_attr,
645 		    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
646 		    &ring, &ring_len,
647 		    &dp->desc_acc_handle)) != DDI_SUCCESS) {
648 			cmn_err(CE_WARN,
649 			    "!%s: %s: ddi_dma_mem_alloc failed: "
650 			    "ret %d, request size: %d",
651 			    dp->name, __func__, err, (int)req_size);
652 			ddi_dma_free_handle(&dp->desc_dma_handle);
653 			return (ENOMEM);
654 		}
655 
656 		if ((err = ddi_dma_addr_bind_handle(dp->desc_dma_handle,
657 		    NULL, ring, ring_len,
658 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
659 		    DDI_DMA_SLEEP, NULL,
660 		    &ring_cookie, &count)) != DDI_SUCCESS) {
661 			ASSERT(err != DDI_DMA_INUSE);
662 			cmn_err(CE_WARN,
663 			    "!%s: %s: ddi_dma_addr_bind_handle failed: %d",
664 			    dp->name, __func__, err);
665 			ddi_dma_mem_free(&dp->desc_acc_handle);
666 			ddi_dma_free_handle(&dp->desc_dma_handle);
667 			return (ENOMEM);
668 		}
669 		ASSERT(count == 1);
670 
671 		/* set base of rx descriptor ring */
672 		dp->rx_ring = ring;
673 		dp->rx_ring_dma = ring_cookie.dmac_laddress;
674 
675 		/* set base of tx descriptor ring */
676 		dp->tx_ring = dp->rx_ring + dp->rx_desc_size;
677 		dp->tx_ring_dma = dp->rx_ring_dma + dp->rx_desc_size;
678 
679 		/* set base of io area */
680 		dp->io_area = dp->tx_ring + dp->tx_desc_size;
681 		dp->io_area_dma = dp->tx_ring_dma + dp->tx_desc_size;
682 	}
683 
684 	/*
685 	 * Prepare DMA resources for tx packets
686 	 */
687 	ASSERT(dp->gc.gc_tx_buf_size > 0);
688 
689 	/* Special dma attribute for tx bounce buffers */
690 	dma_attr_txbounce = dp->gc.gc_dma_attr_txbuf;
691 	dma_attr_txbounce.dma_attr_sgllen = 1;
692 	dma_attr_txbounce.dma_attr_align =
693 	    max(dma_attr_txbounce.dma_attr_align, IOC_LINESIZE);
694 
695 	/* Size for tx bounce buffers must be max tx packet size. */
696 	tx_buf_len = MAXPKTBUF(dp);
697 	tx_buf_len = ROUNDUP(tx_buf_len, IOC_LINESIZE);
698 
699 	ASSERT(tx_buf_len >= ETHERMAX+ETHERFCSL);
700 
701 	for (i = 0, tbp = dp->tx_buf;
702 	    i < dp->gc.gc_tx_buf_size; i++, tbp++) {
703 
704 		/* setup bounce buffers for tx packets */
705 		if ((err = ddi_dma_alloc_handle(dp->dip,
706 		    &dma_attr_txbounce,
707 		    DDI_DMA_SLEEP, NULL,
708 		    &tbp->txb_bdh)) != DDI_SUCCESS) {
709 
710 			cmn_err(CE_WARN,
711 		    "!%s: %s ddi_dma_alloc_handle for bounce buffer failed:"
712 			    " err=%d, i=%d",
713 			    dp->name, __func__, err, i);
714 			goto err_alloc_dh;
715 		}
716 
717 		if ((err = ddi_dma_mem_alloc(tbp->txb_bdh,
718 		    tx_buf_len,
719 		    &dp->gc.gc_buf_attr,
720 		    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
721 		    &buf, &buf_len,
722 		    &tbp->txb_bah)) != DDI_SUCCESS) {
723 			cmn_err(CE_WARN,
724 		    "!%s: %s: ddi_dma_mem_alloc for bounce buffer failed"
725 			    "ret %d, request size %d",
726 			    dp->name, __func__, err, tx_buf_len);
727 			ddi_dma_free_handle(&tbp->txb_bdh);
728 			goto err_alloc_dh;
729 		}
730 
731 		if ((err = ddi_dma_addr_bind_handle(tbp->txb_bdh,
732 		    NULL, buf, buf_len,
733 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
734 		    DDI_DMA_SLEEP, NULL,
735 		    &buf_cookie, &count)) != DDI_SUCCESS) {
736 				ASSERT(err != DDI_DMA_INUSE);
737 				cmn_err(CE_WARN,
738 	"!%s: %s: ddi_dma_addr_bind_handle for bounce buffer failed: %d",
739 				    dp->name, __func__, err);
740 				ddi_dma_mem_free(&tbp->txb_bah);
741 				ddi_dma_free_handle(&tbp->txb_bdh);
742 				goto err_alloc_dh;
743 		}
744 		ASSERT(count == 1);
745 		tbp->txb_buf = buf;
746 		tbp->txb_buf_dma = buf_cookie.dmac_laddress;
747 	}
748 
749 	return (0);
750 
751 err_alloc_dh:
752 	if (dp->gc.gc_tx_buf_size > 0) {
753 		while (i-- > 0) {
754 			(void) ddi_dma_unbind_handle(dp->tx_buf[i].txb_bdh);
755 			ddi_dma_mem_free(&dp->tx_buf[i].txb_bah);
756 			ddi_dma_free_handle(&dp->tx_buf[i].txb_bdh);
757 		}
758 	}
759 
760 	if (dp->desc_dma_handle) {
761 		(void) ddi_dma_unbind_handle(dp->desc_dma_handle);
762 		ddi_dma_mem_free(&dp->desc_acc_handle);
763 		ddi_dma_free_handle(&dp->desc_dma_handle);
764 		dp->desc_dma_handle = NULL;
765 	}
766 
767 	return (ENOMEM);
768 }
769 
770 static void
771 gem_free_memory(struct gem_dev *dp)
772 {
773 	int		i;
774 	struct rxbuf	*rbp;
775 	struct txbuf	*tbp;
776 
777 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
778 
779 	/* Free TX/RX descriptors and tx padding buffer */
780 	if (dp->desc_dma_handle) {
781 		(void) ddi_dma_unbind_handle(dp->desc_dma_handle);
782 		ddi_dma_mem_free(&dp->desc_acc_handle);
783 		ddi_dma_free_handle(&dp->desc_dma_handle);
784 		dp->desc_dma_handle = NULL;
785 	}
786 
787 	/* Free dma handles for Tx */
788 	for (i = dp->gc.gc_tx_buf_size, tbp = dp->tx_buf; i--; tbp++) {
789 		/* Free bounce buffer associated to each txbuf */
790 		(void) ddi_dma_unbind_handle(tbp->txb_bdh);
791 		ddi_dma_mem_free(&tbp->txb_bah);
792 		ddi_dma_free_handle(&tbp->txb_bdh);
793 	}
794 
795 	/* Free rx buffer */
796 	while ((rbp = dp->rx_buf_freelist) != NULL) {
797 
798 		ASSERT(dp->rx_buf_freecnt > 0);
799 
800 		dp->rx_buf_freelist = rbp->rxb_next;
801 		dp->rx_buf_freecnt--;
802 
803 		/* release DMA mapping */
804 		ASSERT(rbp->rxb_dh != NULL);
805 
806 		/* free dma handles for rx bbuf */
807 		/* it has dma mapping always */
808 		ASSERT(rbp->rxb_nfrags > 0);
809 		(void) ddi_dma_unbind_handle(rbp->rxb_dh);
810 
811 		/* free the associated bounce buffer and dma handle */
812 		ASSERT(rbp->rxb_bah != NULL);
813 		ddi_dma_mem_free(&rbp->rxb_bah);
814 		/* free the associated dma handle */
815 		ddi_dma_free_handle(&rbp->rxb_dh);
816 
817 		/* free the base memory of rx buffer management */
818 		kmem_free(rbp, sizeof (struct rxbuf));
819 	}
820 }
821 
822 /* ============================================================== */
823 /*
824  * Rx/Tx descriptor slot management
825  */
826 /* ============================================================== */
827 /*
828  * Initialize an empty rx ring.
829  */
830 static void
831 gem_init_rx_ring(struct gem_dev *dp)
832 {
833 	int		i;
834 	int		rx_ring_size = dp->gc.gc_rx_ring_size;
835 
836 	DPRINTF(1, (CE_CONT, "!%s: %s ring_size:%d, buf_max:%d",
837 	    dp->name, __func__,
838 	    rx_ring_size, dp->gc.gc_rx_buf_max));
839 
840 	/* make a physical chain of rx descriptors */
841 	for (i = 0; i < rx_ring_size; i++) {
842 		(*dp->gc.gc_rx_desc_init)(dp, i);
843 	}
844 	gem_rx_desc_dma_sync(dp, 0, rx_ring_size, DDI_DMA_SYNC_FORDEV);
845 
846 	dp->rx_active_head = (seqnum_t)0;
847 	dp->rx_active_tail = (seqnum_t)0;
848 
849 	ASSERT(dp->rx_buf_head == (struct rxbuf *)NULL);
850 	ASSERT(dp->rx_buf_tail == (struct rxbuf *)NULL);
851 }
852 
853 /*
854  * Prepare rx buffers and put them into the rx buffer/descriptor ring.
855  */
856 static void
857 gem_prepare_rx_buf(struct gem_dev *dp)
858 {
859 	int		i;
860 	int		nrbuf;
861 	struct rxbuf	*rbp;
862 
863 	ASSERT(mutex_owned(&dp->intrlock));
864 
865 	/* Now we have no active buffers in rx ring */
866 
867 	nrbuf = min(dp->gc.gc_rx_ring_size, dp->gc.gc_rx_buf_max);
868 	for (i = 0; i < nrbuf; i++) {
869 		if ((rbp = gem_get_rxbuf(dp, B_TRUE)) == NULL) {
870 			break;
871 		}
872 		gem_append_rxbuf(dp, rbp);
873 	}
874 
875 	gem_rx_desc_dma_sync(dp,
876 	    0, dp->gc.gc_rx_ring_size, DDI_DMA_SYNC_FORDEV);
877 }
878 
879 /*
880  * Reclaim active rx buffers in rx buffer ring.
881  */
882 static void
883 gem_clean_rx_buf(struct gem_dev *dp)
884 {
885 	int		i;
886 	struct rxbuf	*rbp;
887 	int		rx_ring_size = dp->gc.gc_rx_ring_size;
888 #ifdef GEM_DEBUG_LEVEL
889 	int		total;
890 #endif
891 	ASSERT(mutex_owned(&dp->intrlock));
892 
893 	DPRINTF(2, (CE_CONT, "!%s: %s: %d buffers are free",
894 	    dp->name, __func__, dp->rx_buf_freecnt));
895 	/*
896 	 * clean up HW descriptors
897 	 */
898 	for (i = 0; i < rx_ring_size; i++) {
899 		(*dp->gc.gc_rx_desc_clean)(dp, i);
900 	}
901 	gem_rx_desc_dma_sync(dp, 0, rx_ring_size, DDI_DMA_SYNC_FORDEV);
902 
903 #ifdef GEM_DEBUG_LEVEL
904 	total = 0;
905 #endif
906 	/*
907 	 * Reclaim allocated rx buffers
908 	 */
909 	while ((rbp = dp->rx_buf_head) != NULL) {
910 #ifdef GEM_DEBUG_LEVEL
911 		total++;
912 #endif
913 		/* remove the first one from rx buffer list */
914 		dp->rx_buf_head = rbp->rxb_next;
915 
916 		/* recycle the rxbuf */
917 		gem_free_rxbuf(rbp);
918 	}
919 	dp->rx_buf_tail = (struct rxbuf *)NULL;
920 
921 	DPRINTF(2, (CE_CONT,
922 	    "!%s: %s: %d buffers freeed, total: %d free",
923 	    dp->name, __func__, total, dp->rx_buf_freecnt));
924 }
925 
926 /*
927  * Initialize an empty transmit buffer/descriptor ring
928  */
929 static void
930 gem_init_tx_ring(struct gem_dev *dp)
931 {
932 	int		i;
933 	int		tx_buf_size = dp->gc.gc_tx_buf_size;
934 	int		tx_ring_size = dp->gc.gc_tx_ring_size;
935 
936 	DPRINTF(2, (CE_CONT, "!%s: %s: ring_size:%d, buf_size:%d",
937 	    dp->name, __func__,
938 	    dp->gc.gc_tx_ring_size, dp->gc.gc_tx_buf_size));
939 
940 	ASSERT(!dp->mac_active);
941 
942 	/* initialize active list and free list */
943 	dp->tx_slots_base =
944 	    SLOT(dp->tx_slots_base + dp->tx_softq_head, tx_buf_size);
945 	dp->tx_softq_tail -= dp->tx_softq_head;
946 	dp->tx_softq_head = (seqnum_t)0;
947 
948 	dp->tx_active_head = dp->tx_softq_head;
949 	dp->tx_active_tail = dp->tx_softq_head;
950 
951 	dp->tx_free_head   = dp->tx_softq_tail;
952 	dp->tx_free_tail   = dp->gc.gc_tx_buf_limit;
953 
954 	dp->tx_desc_head = (seqnum_t)0;
955 	dp->tx_desc_tail = (seqnum_t)0;
956 	dp->tx_desc_intr = (seqnum_t)0;
957 
958 	for (i = 0; i < tx_ring_size; i++) {
959 		(*dp->gc.gc_tx_desc_init)(dp, i);
960 	}
961 	gem_tx_desc_dma_sync(dp, 0, tx_ring_size, DDI_DMA_SYNC_FORDEV);
962 }
963 
964 __INLINE__
965 static void
966 gem_txbuf_free_dma_resources(struct txbuf *tbp)
967 {
968 	if (tbp->txb_mp) {
969 		freemsg(tbp->txb_mp);
970 		tbp->txb_mp = NULL;
971 	}
972 	tbp->txb_nfrags = 0;
973 	tbp->txb_flag = 0;
974 }
975 #pragma inline(gem_txbuf_free_dma_resources)
976 
977 /*
978  * reclaim active tx buffers and reset positions in tx rings.
979  */
980 static void
981 gem_clean_tx_buf(struct gem_dev *dp)
982 {
983 	int		i;
984 	seqnum_t	head;
985 	seqnum_t	tail;
986 	seqnum_t	sn;
987 	struct txbuf	*tbp;
988 	int		tx_ring_size = dp->gc.gc_tx_ring_size;
989 #ifdef GEM_DEBUG_LEVEL
990 	int		err;
991 #endif
992 
993 	ASSERT(!dp->mac_active);
994 	ASSERT(dp->tx_busy == 0);
995 	ASSERT(dp->tx_softq_tail == dp->tx_free_head);
996 
997 	/*
998 	 * clean up all HW descriptors
999 	 */
1000 	for (i = 0; i < tx_ring_size; i++) {
1001 		(*dp->gc.gc_tx_desc_clean)(dp, i);
1002 	}
1003 	gem_tx_desc_dma_sync(dp, 0, tx_ring_size, DDI_DMA_SYNC_FORDEV);
1004 
1005 	/* dequeue all active and loaded buffers */
1006 	head = dp->tx_active_head;
1007 	tail = dp->tx_softq_tail;
1008 
1009 	ASSERT(dp->tx_free_head - head >= 0);
1010 	tbp = GET_TXBUF(dp, head);
1011 	for (sn = head; sn != tail; sn++) {
1012 		gem_txbuf_free_dma_resources(tbp);
1013 		ASSERT(tbp->txb_mp == NULL);
1014 		dp->stats.errxmt++;
1015 		tbp = tbp->txb_next;
1016 	}
1017 
1018 #ifdef GEM_DEBUG_LEVEL
1019 	/* ensure no dma resources for tx are not in use now */
1020 	err = 0;
1021 	while (sn != head + dp->gc.gc_tx_buf_size) {
1022 		if (tbp->txb_mp || tbp->txb_nfrags) {
1023 			DPRINTF(0, (CE_CONT,
1024 			    "%s: %s: sn:%d[%d] mp:%p nfrags:%d",
1025 			    dp->name, __func__,
1026 			    sn, SLOT(sn, dp->gc.gc_tx_buf_size),
1027 			    tbp->txb_mp, tbp->txb_nfrags));
1028 			err = 1;
1029 		}
1030 		sn++;
1031 		tbp = tbp->txb_next;
1032 	}
1033 
1034 	if (err) {
1035 		gem_dump_txbuf(dp, CE_WARN,
1036 		    "gem_clean_tx_buf: tbp->txb_mp != NULL");
1037 	}
1038 #endif
1039 	/* recycle buffers, now no active tx buffers in the ring */
1040 	dp->tx_free_tail += tail - head;
1041 	ASSERT(dp->tx_free_tail == dp->tx_free_head + dp->gc.gc_tx_buf_limit);
1042 
1043 	/* fix positions in tx buffer rings */
1044 	dp->tx_active_head = dp->tx_free_head;
1045 	dp->tx_active_tail = dp->tx_free_head;
1046 	dp->tx_softq_head  = dp->tx_free_head;
1047 	dp->tx_softq_tail  = dp->tx_free_head;
1048 }
1049 
1050 /*
1051  * Reclaim transmitted buffers from tx buffer/descriptor ring.
1052  */
1053 __INLINE__ int
1054 gem_reclaim_txbuf(struct gem_dev *dp)
1055 {
1056 	struct txbuf	*tbp;
1057 	uint_t		txstat;
1058 	int		err = GEM_SUCCESS;
1059 	seqnum_t	head;
1060 	seqnum_t	tail;
1061 	seqnum_t	sn;
1062 	seqnum_t	desc_head;
1063 	int		tx_ring_size = dp->gc.gc_tx_ring_size;
1064 	uint_t (*tx_desc_stat)(struct gem_dev *dp,
1065 	    int slot, int ndesc) = dp->gc.gc_tx_desc_stat;
1066 	clock_t		now;
1067 
1068 	now = ddi_get_lbolt();
1069 	if (now == (clock_t)0) {
1070 		/* make non-zero timestamp */
1071 		now--;
1072 	}
1073 
1074 	mutex_enter(&dp->xmitlock);
1075 
1076 	head = dp->tx_active_head;
1077 	tail = dp->tx_active_tail;
1078 
1079 #if GEM_DEBUG_LEVEL > 2
1080 	if (head != tail) {
1081 		cmn_err(CE_CONT, "!%s: %s: "
1082 		    "testing active_head:%d[%d], active_tail:%d[%d]",
1083 		    dp->name, __func__,
1084 		    head, SLOT(head, dp->gc.gc_tx_buf_size),
1085 		    tail, SLOT(tail, dp->gc.gc_tx_buf_size));
1086 	}
1087 #endif
1088 #ifdef DEBUG
1089 	if (dp->tx_reclaim_busy == 0) {
1090 		/* check tx buffer management consistency */
1091 		ASSERT(dp->tx_free_tail - dp->tx_active_head
1092 		    == dp->gc.gc_tx_buf_limit);
1093 		/* EMPTY */
1094 	}
1095 #endif
1096 	dp->tx_reclaim_busy++;
1097 
1098 	/* sync all active HW descriptors */
1099 	gem_tx_desc_dma_sync(dp,
1100 	    SLOT(dp->tx_desc_head, tx_ring_size),
1101 	    dp->tx_desc_tail - dp->tx_desc_head,
1102 	    DDI_DMA_SYNC_FORKERNEL);
1103 
1104 	tbp = GET_TXBUF(dp, head);
1105 	desc_head = dp->tx_desc_head;
1106 	for (sn = head; sn != tail;
1107 	    dp->tx_active_head = (++sn), tbp = tbp->txb_next) {
1108 		int	ndescs;
1109 
1110 		ASSERT(tbp->txb_desc == desc_head);
1111 
1112 		ndescs = tbp->txb_ndescs;
1113 		if (ndescs == 0) {
1114 			/* skip errored descriptors */
1115 			continue;
1116 		}
1117 		txstat = (*tx_desc_stat)(dp,
1118 		    SLOT(tbp->txb_desc, tx_ring_size), ndescs);
1119 
1120 		if (txstat == 0) {
1121 			/* not transmitted yet */
1122 			break;
1123 		}
1124 
1125 		if (!dp->tx_blocked && (tbp->txb_flag & GEM_TXFLAG_INTR)) {
1126 			dp->tx_blocked = now;
1127 		}
1128 
1129 		ASSERT(txstat & (GEM_TX_DONE | GEM_TX_ERR));
1130 
1131 		if (txstat & GEM_TX_ERR) {
1132 			err = GEM_FAILURE;
1133 			cmn_err(CE_WARN, "!%s: tx error at desc %d[%d]",
1134 			    dp->name, sn, SLOT(sn, tx_ring_size));
1135 		}
1136 #if GEM_DEBUG_LEVEL > 4
1137 		if (now - tbp->txb_stime >= 50) {
1138 			cmn_err(CE_WARN, "!%s: tx delay while %d mS",
1139 			    dp->name, (now - tbp->txb_stime)*10);
1140 		}
1141 #endif
1142 		/* free transmitted descriptors */
1143 		desc_head += ndescs;
1144 	}
1145 
1146 	if (dp->tx_desc_head != desc_head) {
1147 		/* we have reclaimed one or more tx buffers */
1148 		dp->tx_desc_head = desc_head;
1149 
1150 		/* If we passed the next interrupt position, update it */
1151 		if (desc_head - dp->tx_desc_intr > 0) {
1152 			dp->tx_desc_intr = desc_head;
1153 		}
1154 	}
1155 	mutex_exit(&dp->xmitlock);
1156 
1157 	/* free dma mapping resources associated with transmitted tx buffers */
1158 	tbp = GET_TXBUF(dp, head);
1159 	tail = sn;
1160 #if GEM_DEBUG_LEVEL > 2
1161 	if (head != tail) {
1162 		cmn_err(CE_CONT, "%s: freeing head:%d[%d], tail:%d[%d]",
1163 		    __func__,
1164 		    head, SLOT(head, dp->gc.gc_tx_buf_size),
1165 		    tail, SLOT(tail, dp->gc.gc_tx_buf_size));
1166 	}
1167 #endif
1168 	for (sn = head; sn != tail; sn++, tbp = tbp->txb_next) {
1169 		gem_txbuf_free_dma_resources(tbp);
1170 	}
1171 
1172 	/* recycle the tx buffers */
1173 	mutex_enter(&dp->xmitlock);
1174 	if (--dp->tx_reclaim_busy == 0) {
1175 		/* we are the last thread who can update free tail */
1176 #if GEM_DEBUG_LEVEL > 4
1177 		/* check all resouces have been deallocated */
1178 		sn = dp->tx_free_tail;
1179 		tbp = GET_TXBUF(dp, new_tail);
1180 		while (sn != dp->tx_active_head + dp->gc.gc_tx_buf_limit) {
1181 			if (tbp->txb_nfrags) {
1182 				/* in use */
1183 				break;
1184 			}
1185 			ASSERT(tbp->txb_mp == NULL);
1186 			tbp = tbp->txb_next;
1187 			sn++;
1188 		}
1189 		ASSERT(dp->tx_active_head + dp->gc.gc_tx_buf_limit == sn);
1190 #endif
1191 		dp->tx_free_tail =
1192 		    dp->tx_active_head + dp->gc.gc_tx_buf_limit;
1193 	}
1194 	if (!dp->mac_active) {
1195 		/* someone may be waiting for me. */
1196 		cv_broadcast(&dp->tx_drain_cv);
1197 	}
1198 #if GEM_DEBUG_LEVEL > 2
1199 	cmn_err(CE_CONT, "!%s: %s: called, "
1200 	    "free_head:%d free_tail:%d(+%d) added:%d",
1201 	    dp->name, __func__,
1202 	    dp->tx_free_head, dp->tx_free_tail,
1203 	    dp->tx_free_tail - dp->tx_free_head, tail - head);
1204 #endif
1205 	mutex_exit(&dp->xmitlock);
1206 
1207 	return (err);
1208 }
1209 #pragma inline(gem_reclaim_txbuf)
1210 
1211 
1212 /*
1213  * Make tx descriptors in out-of-order manner
1214  */
1215 static void
1216 gem_tx_load_descs_oo(struct gem_dev *dp,
1217 	seqnum_t start_slot, seqnum_t end_slot, uint64_t flags)
1218 {
1219 	seqnum_t	sn;
1220 	struct txbuf	*tbp;
1221 	int	tx_ring_size = dp->gc.gc_tx_ring_size;
1222 	int	(*tx_desc_write)
1223 	    (struct gem_dev *dp, int slot,
1224 	    ddi_dma_cookie_t *dmacookie,
1225 	    int frags, uint64_t flag) = dp->gc.gc_tx_desc_write;
1226 	clock_t	now = ddi_get_lbolt();
1227 
1228 	sn = start_slot;
1229 	tbp = GET_TXBUF(dp, sn);
1230 	do {
1231 #if GEM_DEBUG_LEVEL > 1
1232 		if (dp->tx_cnt < 100) {
1233 			dp->tx_cnt++;
1234 			flags |= GEM_TXFLAG_INTR;
1235 		}
1236 #endif
1237 		/* write a tx descriptor */
1238 		tbp->txb_desc = sn;
1239 		tbp->txb_ndescs = (*tx_desc_write)(dp,
1240 		    SLOT(sn, tx_ring_size),
1241 		    tbp->txb_dmacookie,
1242 		    tbp->txb_nfrags, flags | tbp->txb_flag);
1243 		tbp->txb_stime = now;
1244 		ASSERT(tbp->txb_ndescs == 1);
1245 
1246 		flags = 0;
1247 		sn++;
1248 		tbp = tbp->txb_next;
1249 	} while (sn != end_slot);
1250 }
1251 
1252 __INLINE__
1253 static size_t
1254 gem_setup_txbuf_copy(struct gem_dev *dp, mblk_t *mp, struct txbuf *tbp)
1255 {
1256 	size_t			min_pkt;
1257 	caddr_t			bp;
1258 	size_t			off;
1259 	mblk_t			*tp;
1260 	size_t			len;
1261 	uint64_t		flag;
1262 
1263 	ASSERT(tbp->txb_mp == NULL);
1264 
1265 	/* we use bounce buffer for the packet */
1266 	min_pkt = ETHERMIN;
1267 	bp = tbp->txb_buf;
1268 	off = 0;
1269 	tp = mp;
1270 
1271 	flag = tbp->txb_flag;
1272 	if (flag & GEM_TXFLAG_SWVTAG) {
1273 		/* need to increase min packet size */
1274 		min_pkt += VTAG_SIZE;
1275 		ASSERT((flag & GEM_TXFLAG_VTAG) == 0);
1276 	}
1277 
1278 	/* copy the rest */
1279 	for (; tp; tp = tp->b_cont) {
1280 		if ((len = (long)tp->b_wptr - (long)tp->b_rptr) > 0) {
1281 			bcopy(tp->b_rptr, &bp[off], len);
1282 			off += len;
1283 		}
1284 	}
1285 
1286 	if (off < min_pkt &&
1287 	    (min_pkt > ETHERMIN || !dp->gc.gc_tx_auto_pad)) {
1288 		/*
1289 		 * Extend the packet to minimum packet size explicitly.
1290 		 * For software vlan packets, we shouldn't use tx autopad
1291 		 * function because nics may not be aware of vlan.
1292 		 * we must keep 46 octet of payload even if we use vlan.
1293 		 */
1294 		bzero(&bp[off], min_pkt - off);
1295 		off = min_pkt;
1296 	}
1297 
1298 	(void) ddi_dma_sync(tbp->txb_bdh, (off_t)0, off, DDI_DMA_SYNC_FORDEV);
1299 
1300 	tbp->txb_dmacookie[0].dmac_laddress = tbp->txb_buf_dma;
1301 	tbp->txb_dmacookie[0].dmac_size = off;
1302 
1303 	DPRINTF(2, (CE_CONT,
1304 	    "!%s: %s: copy: addr:0x%llx len:0x%x, vtag:0x%04x, min_pkt:%d",
1305 	    dp->name, __func__,
1306 	    tbp->txb_dmacookie[0].dmac_laddress,
1307 	    tbp->txb_dmacookie[0].dmac_size,
1308 	    (flag & GEM_TXFLAG_VTAG) >> GEM_TXFLAG_VTAG_SHIFT,
1309 	    min_pkt));
1310 
1311 	/* save misc info */
1312 	tbp->txb_mp = mp;
1313 	tbp->txb_nfrags = 1;
1314 #ifdef DEBUG_MULTIFRAGS
1315 	if (dp->gc.gc_tx_max_frags >= 3 &&
1316 	    tbp->txb_dmacookie[0].dmac_size > 16*3) {
1317 		tbp->txb_dmacookie[1].dmac_laddress =
1318 		    tbp->txb_dmacookie[0].dmac_laddress + 16;
1319 		tbp->txb_dmacookie[2].dmac_laddress =
1320 		    tbp->txb_dmacookie[1].dmac_laddress + 16;
1321 
1322 		tbp->txb_dmacookie[2].dmac_size =
1323 		    tbp->txb_dmacookie[0].dmac_size - 16*2;
1324 		tbp->txb_dmacookie[1].dmac_size = 16;
1325 		tbp->txb_dmacookie[0].dmac_size = 16;
1326 		tbp->txb_nfrags  = 3;
1327 	}
1328 #endif
1329 	return (off);
1330 }
1331 #pragma inline(gem_setup_txbuf_copy)
1332 
1333 __INLINE__
1334 static void
1335 gem_tx_start_unit(struct gem_dev *dp)
1336 {
1337 	seqnum_t	head;
1338 	seqnum_t	tail;
1339 	struct txbuf	*tbp_head;
1340 	struct txbuf	*tbp_tail;
1341 
1342 	/* update HW descriptors from soft queue */
1343 	ASSERT(mutex_owned(&dp->xmitlock));
1344 	ASSERT(dp->tx_softq_head == dp->tx_active_tail);
1345 
1346 	head = dp->tx_softq_head;
1347 	tail = dp->tx_softq_tail;
1348 
1349 	DPRINTF(1, (CE_CONT,
1350 	    "%s: %s: called, softq %d %d[+%d], desc %d %d[+%d]",
1351 	    dp->name, __func__, head, tail, tail - head,
1352 	    dp->tx_desc_head, dp->tx_desc_tail,
1353 	    dp->tx_desc_tail - dp->tx_desc_head));
1354 
1355 	ASSERT(tail - head > 0);
1356 
1357 	dp->tx_desc_tail = tail;
1358 
1359 	tbp_head = GET_TXBUF(dp, head);
1360 	tbp_tail = GET_TXBUF(dp, tail - 1);
1361 
1362 	ASSERT(tbp_tail->txb_desc + tbp_tail->txb_ndescs == dp->tx_desc_tail);
1363 
1364 	dp->gc.gc_tx_start(dp,
1365 	    SLOT(tbp_head->txb_desc, dp->gc.gc_tx_ring_size),
1366 	    tbp_tail->txb_desc + tbp_tail->txb_ndescs - tbp_head->txb_desc);
1367 
1368 	/* advance softq head and active tail */
1369 	dp->tx_softq_head = dp->tx_active_tail = tail;
1370 }
1371 #pragma inline(gem_tx_start_unit)
1372 
1373 #ifdef GEM_DEBUG_LEVEL
1374 static int gem_send_cnt[10];
1375 #endif
1376 #define	PKT_MIN_SIZE	(sizeof (struct ether_header) + 10 + VTAG_SIZE)
1377 #define	EHLEN	(sizeof (struct ether_header))
1378 /*
1379  * check ether packet type and ip protocol
1380  */
1381 static uint64_t
1382 gem_txbuf_options(struct gem_dev *dp, mblk_t *mp, uint8_t *bp)
1383 {
1384 	mblk_t		*tp;
1385 	ssize_t		len;
1386 	uint_t		vtag;
1387 	int		off;
1388 	uint64_t	flag;
1389 
1390 	flag = 0ULL;
1391 
1392 	/*
1393 	 * prepare continuous header of the packet for protocol analysis
1394 	 */
1395 	if ((long)mp->b_wptr - (long)mp->b_rptr < PKT_MIN_SIZE) {
1396 		/* we use work buffer to copy mblk */
1397 		for (tp = mp, off = 0;
1398 		    tp && (off < PKT_MIN_SIZE);
1399 		    tp = tp->b_cont, off += len) {
1400 			len = (long)tp->b_wptr - (long)tp->b_rptr;
1401 			len = min(len, PKT_MIN_SIZE - off);
1402 			bcopy(tp->b_rptr, &bp[off], len);
1403 		}
1404 	} else {
1405 		/* we can use mblk without copy */
1406 		bp = mp->b_rptr;
1407 	}
1408 
1409 	/* process vlan tag for GLD v3 */
1410 	if (GET_NET16(&bp[VTAG_OFF]) == VTAG_TPID) {
1411 		if (dp->misc_flag & GEM_VLAN_HARD) {
1412 			vtag = GET_NET16(&bp[VTAG_OFF + 2]);
1413 			ASSERT(vtag);
1414 			flag |= vtag << GEM_TXFLAG_VTAG_SHIFT;
1415 		} else {
1416 			flag |= GEM_TXFLAG_SWVTAG;
1417 		}
1418 	}
1419 	return (flag);
1420 }
1421 #undef EHLEN
1422 #undef PKT_MIN_SIZE
1423 /*
1424  * gem_send_common is an exported function because hw depend routines may
1425  * use it for sending control frames like setup frames for 2114x chipset.
1426  */
1427 mblk_t *
1428 gem_send_common(struct gem_dev *dp, mblk_t *mp_head, uint32_t flags)
1429 {
1430 	int			nmblk;
1431 	int			avail;
1432 	mblk_t			*tp;
1433 	mblk_t			*mp;
1434 	int			i;
1435 	struct txbuf		*tbp;
1436 	seqnum_t		head;
1437 	uint64_t		load_flags;
1438 	uint64_t		len_total = 0;
1439 	uint32_t		bcast = 0;
1440 	uint32_t		mcast = 0;
1441 
1442 	ASSERT(mp_head != NULL);
1443 
1444 	mp = mp_head;
1445 	nmblk = 1;
1446 	while ((mp = mp->b_next) != NULL) {
1447 		nmblk++;
1448 	}
1449 #ifdef GEM_DEBUG_LEVEL
1450 	gem_send_cnt[0]++;
1451 	gem_send_cnt[min(nmblk, 9)]++;
1452 #endif
1453 	/*
1454 	 * Aquire resources
1455 	 */
1456 	mutex_enter(&dp->xmitlock);
1457 	if (dp->mac_suspended) {
1458 		mutex_exit(&dp->xmitlock);
1459 		mp = mp_head;
1460 		while (mp) {
1461 			tp = mp->b_next;
1462 			freemsg(mp);
1463 			mp = tp;
1464 		}
1465 		return (NULL);
1466 	}
1467 
1468 	if (!dp->mac_active && (flags & GEM_SEND_CTRL) == 0) {
1469 		/* don't send data packets while mac isn't active */
1470 		/* XXX - should we discard packets? */
1471 		mutex_exit(&dp->xmitlock);
1472 		return (mp_head);
1473 	}
1474 
1475 	/* allocate free slots */
1476 	head = dp->tx_free_head;
1477 	avail = dp->tx_free_tail - head;
1478 
1479 	DPRINTF(2, (CE_CONT,
1480 	    "!%s: %s: called, free_head:%d free_tail:%d(+%d) req:%d",
1481 	    dp->name, __func__,
1482 	    dp->tx_free_head, dp->tx_free_tail, avail, nmblk));
1483 
1484 	avail = min(avail, dp->tx_max_packets);
1485 
1486 	if (nmblk > avail) {
1487 		if (avail == 0) {
1488 			/* no resources; short cut */
1489 			DPRINTF(2, (CE_CONT, "!%s: no resources", __func__));
1490 			dp->tx_max_packets = max(dp->tx_max_packets - 1, 1);
1491 			goto done;
1492 		}
1493 		nmblk = avail;
1494 	}
1495 
1496 	dp->tx_free_head = head + nmblk;
1497 	load_flags = ((dp->tx_busy++) == 0) ? GEM_TXFLAG_HEAD : 0;
1498 
1499 	/* update last interrupt position if tx buffers exhaust.  */
1500 	if (nmblk == avail) {
1501 		tbp = GET_TXBUF(dp, head + avail - 1);
1502 		tbp->txb_flag = GEM_TXFLAG_INTR;
1503 		dp->tx_desc_intr = head + avail;
1504 	}
1505 	mutex_exit(&dp->xmitlock);
1506 
1507 	tbp = GET_TXBUF(dp, head);
1508 
1509 	for (i = nmblk; i > 0; i--, tbp = tbp->txb_next) {
1510 		uint8_t		*bp;
1511 		uint64_t	txflag;
1512 
1513 		/* remove one from the mblk list */
1514 		ASSERT(mp_head != NULL);
1515 		mp = mp_head;
1516 		mp_head = mp_head->b_next;
1517 		mp->b_next = NULL;
1518 
1519 		/* statistics for non-unicast packets */
1520 		bp = mp->b_rptr;
1521 		if ((bp[0] & 1) && (flags & GEM_SEND_CTRL) == 0) {
1522 			if (bcmp(bp, gem_etherbroadcastaddr.ether_addr_octet,
1523 			    ETHERADDRL) == 0) {
1524 				bcast++;
1525 			} else {
1526 				mcast++;
1527 			}
1528 		}
1529 
1530 		/* save misc info */
1531 		txflag = tbp->txb_flag;
1532 		txflag |= (flags & GEM_SEND_CTRL) << GEM_TXFLAG_PRIVATE_SHIFT;
1533 		txflag |= gem_txbuf_options(dp, mp, (uint8_t *)tbp->txb_buf);
1534 		tbp->txb_flag = txflag;
1535 
1536 		len_total += gem_setup_txbuf_copy(dp, mp, tbp);
1537 	}
1538 
1539 	(void) gem_tx_load_descs_oo(dp, head, head + nmblk, load_flags);
1540 
1541 	/* Append the tbp at the tail of the active tx buffer list */
1542 	mutex_enter(&dp->xmitlock);
1543 
1544 	if ((--dp->tx_busy) == 0) {
1545 		/* extend the tail of softq, as new packets have been ready. */
1546 		dp->tx_softq_tail = dp->tx_free_head;
1547 
1548 		if (!dp->mac_active && (flags & GEM_SEND_CTRL) == 0) {
1549 			/*
1550 			 * The device status has changed while we are
1551 			 * preparing tx buf.
1552 			 * As we are the last one that make tx non-busy.
1553 			 * wake up someone who may wait for us.
1554 			 */
1555 			cv_broadcast(&dp->tx_drain_cv);
1556 		} else {
1557 			ASSERT(dp->tx_softq_tail - dp->tx_softq_head > 0);
1558 			gem_tx_start_unit(dp);
1559 		}
1560 	}
1561 	dp->stats.obytes += len_total;
1562 	dp->stats.opackets += nmblk;
1563 	dp->stats.obcast += bcast;
1564 	dp->stats.omcast += mcast;
1565 done:
1566 	mutex_exit(&dp->xmitlock);
1567 
1568 	return (mp_head);
1569 }
1570 
1571 /* ========================================================== */
1572 /*
1573  * error detection and restart routines
1574  */
1575 /* ========================================================== */
1576 int
1577 gem_restart_nic(struct gem_dev *dp, uint_t flags)
1578 {
1579 	ASSERT(mutex_owned(&dp->intrlock));
1580 
1581 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
1582 #ifdef GEM_DEBUG_LEVEL
1583 #if GEM_DEBUG_LEVEL > 1
1584 	gem_dump_txbuf(dp, CE_CONT, "gem_restart_nic");
1585 #endif
1586 #endif
1587 
1588 	if (dp->mac_suspended) {
1589 		/* should we return GEM_FAILURE ? */
1590 		return (GEM_FAILURE);
1591 	}
1592 
1593 	/*
1594 	 * We should avoid calling any routines except xxx_chip_reset
1595 	 * when we are resuming the system.
1596 	 */
1597 	if (dp->mac_active) {
1598 		if (flags & GEM_RESTART_KEEP_BUF) {
1599 			/* stop rx gracefully */
1600 			dp->rxmode &= ~RXMODE_ENABLE;
1601 			(void) (*dp->gc.gc_set_rx_filter)(dp);
1602 		}
1603 		(void) gem_mac_stop(dp, flags);
1604 	}
1605 
1606 	/* reset the chip. */
1607 	if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
1608 		cmn_err(CE_WARN, "%s: %s: failed to reset chip",
1609 		    dp->name, __func__);
1610 		goto err;
1611 	}
1612 
1613 	if (gem_mac_init(dp) != GEM_SUCCESS) {
1614 		goto err;
1615 	}
1616 
1617 	/* setup media mode if the link have been up */
1618 	if (dp->mii_state == MII_STATE_LINKUP) {
1619 		if ((dp->gc.gc_set_media)(dp) != GEM_SUCCESS) {
1620 			goto err;
1621 		}
1622 	}
1623 
1624 	/* setup mac address and enable rx filter */
1625 	dp->rxmode |= RXMODE_ENABLE;
1626 	if ((*dp->gc.gc_set_rx_filter)(dp) != GEM_SUCCESS) {
1627 		goto err;
1628 	}
1629 
1630 	/*
1631 	 * XXX - a panic happened because of linkdown.
1632 	 * We must check mii_state here, because the link can be down just
1633 	 * before the restart event happen. If the link is down now,
1634 	 * gem_mac_start() will be called from gem_mii_link_check() when
1635 	 * the link become up later.
1636 	 */
1637 	if (dp->mii_state == MII_STATE_LINKUP) {
1638 		/* restart the nic */
1639 		ASSERT(!dp->mac_active);
1640 		(void) gem_mac_start(dp);
1641 	}
1642 	return (GEM_SUCCESS);
1643 err:
1644 	return (GEM_FAILURE);
1645 }
1646 
1647 
1648 static void
1649 gem_tx_timeout(struct gem_dev *dp)
1650 {
1651 	clock_t		now;
1652 	boolean_t	tx_sched;
1653 	struct txbuf	*tbp;
1654 
1655 	mutex_enter(&dp->intrlock);
1656 
1657 	tx_sched = B_FALSE;
1658 	now = ddi_get_lbolt();
1659 
1660 	mutex_enter(&dp->xmitlock);
1661 	if (!dp->mac_active || dp->mii_state != MII_STATE_LINKUP) {
1662 		mutex_exit(&dp->xmitlock);
1663 		goto schedule_next;
1664 	}
1665 	mutex_exit(&dp->xmitlock);
1666 
1667 	/* reclaim transmitted buffers to check the trasmitter hangs or not. */
1668 	if (gem_reclaim_txbuf(dp) != GEM_SUCCESS) {
1669 		/* tx error happened, reset transmitter in the chip */
1670 		(void) gem_restart_nic(dp, 0);
1671 		tx_sched = B_TRUE;
1672 		dp->tx_blocked = (clock_t)0;
1673 
1674 		goto schedule_next;
1675 	}
1676 
1677 	mutex_enter(&dp->xmitlock);
1678 	/* check if the transmitter thread is stuck */
1679 	if (dp->tx_active_head == dp->tx_active_tail) {
1680 		/* no tx buffer is loaded to the nic */
1681 		if (dp->tx_blocked &&
1682 		    now - dp->tx_blocked > dp->gc.gc_tx_timeout_interval) {
1683 			gem_dump_txbuf(dp, CE_WARN,
1684 			    "gem_tx_timeout: tx blocked");
1685 			tx_sched = B_TRUE;
1686 			dp->tx_blocked = (clock_t)0;
1687 		}
1688 		mutex_exit(&dp->xmitlock);
1689 		goto schedule_next;
1690 	}
1691 
1692 	tbp = GET_TXBUF(dp, dp->tx_active_head);
1693 	if (now - tbp->txb_stime < dp->gc.gc_tx_timeout) {
1694 		mutex_exit(&dp->xmitlock);
1695 		goto schedule_next;
1696 	}
1697 	mutex_exit(&dp->xmitlock);
1698 
1699 	gem_dump_txbuf(dp, CE_WARN, "gem_tx_timeout: tx timeout");
1700 
1701 	/* discard untransmitted packet and restart tx.  */
1702 	(void) gem_restart_nic(dp, GEM_RESTART_NOWAIT);
1703 	tx_sched = B_TRUE;
1704 	dp->tx_blocked = (clock_t)0;
1705 
1706 schedule_next:
1707 	mutex_exit(&dp->intrlock);
1708 
1709 	/* restart the downstream if needed */
1710 	if (tx_sched) {
1711 		mac_tx_update(dp->mh);
1712 	}
1713 
1714 	DPRINTF(4, (CE_CONT,
1715 	    "!%s: blocked:%d active_head:%d active_tail:%d desc_intr:%d",
1716 	    dp->name, BOOLEAN(dp->tx_blocked),
1717 	    dp->tx_active_head, dp->tx_active_tail, dp->tx_desc_intr));
1718 	dp->timeout_id =
1719 	    timeout((void (*)(void *))gem_tx_timeout,
1720 	    (void *)dp, dp->gc.gc_tx_timeout_interval);
1721 }
1722 
1723 /* ================================================================== */
1724 /*
1725  * Interrupt handler
1726  */
1727 /* ================================================================== */
1728 __INLINE__
1729 static void
1730 gem_append_rxbuf(struct gem_dev *dp, struct rxbuf *rbp_head)
1731 {
1732 	struct rxbuf	*rbp;
1733 	seqnum_t	tail;
1734 	int		rx_ring_size = dp->gc.gc_rx_ring_size;
1735 
1736 	ASSERT(rbp_head != NULL);
1737 	ASSERT(mutex_owned(&dp->intrlock));
1738 
1739 	DPRINTF(3, (CE_CONT, "!%s: %s: slot_head:%d, slot_tail:%d",
1740 	    dp->name, __func__, dp->rx_active_head, dp->rx_active_tail));
1741 
1742 	/*
1743 	 * Add new buffers into active rx buffer list
1744 	 */
1745 	if (dp->rx_buf_head == NULL) {
1746 		dp->rx_buf_head = rbp_head;
1747 		ASSERT(dp->rx_buf_tail == NULL);
1748 	} else {
1749 		dp->rx_buf_tail->rxb_next = rbp_head;
1750 	}
1751 
1752 	tail = dp->rx_active_tail;
1753 	for (rbp = rbp_head; rbp; rbp = rbp->rxb_next) {
1754 		/* need to notify the tail for the lower layer */
1755 		dp->rx_buf_tail = rbp;
1756 
1757 		dp->gc.gc_rx_desc_write(dp,
1758 		    SLOT(tail, rx_ring_size),
1759 		    rbp->rxb_dmacookie,
1760 		    rbp->rxb_nfrags);
1761 
1762 		dp->rx_active_tail = tail = tail + 1;
1763 	}
1764 }
1765 #pragma inline(gem_append_rxbuf)
1766 
1767 mblk_t *
1768 gem_get_packet_default(struct gem_dev *dp, struct rxbuf *rbp, size_t len)
1769 {
1770 	int		rx_header_len = dp->gc.gc_rx_header_len;
1771 	uint8_t		*bp;
1772 	mblk_t		*mp;
1773 
1774 	/* allocate a new mblk */
1775 	if (mp = allocb(len + VTAG_SIZE, BPRI_MED)) {
1776 		ASSERT(mp->b_next == NULL);
1777 		ASSERT(mp->b_cont == NULL);
1778 
1779 		mp->b_rptr += VTAG_SIZE;
1780 		bp = mp->b_rptr;
1781 		mp->b_wptr = bp + len;
1782 
1783 		/*
1784 		 * flush the range of the entire buffer to invalidate
1785 		 * all of corresponding dirty entries in iocache.
1786 		 */
1787 		(void) ddi_dma_sync(rbp->rxb_dh, rx_header_len,
1788 		    0, DDI_DMA_SYNC_FORKERNEL);
1789 
1790 		bcopy(rbp->rxb_buf + rx_header_len, bp, len);
1791 	}
1792 	return (mp);
1793 }
1794 
1795 #ifdef GEM_DEBUG_LEVEL
1796 uint_t	gem_rx_pkts[17];
1797 #endif
1798 
1799 
1800 int
1801 gem_receive(struct gem_dev *dp)
1802 {
1803 	uint64_t	len_total = 0;
1804 	struct rxbuf	*rbp;
1805 	mblk_t		*mp;
1806 	int		cnt = 0;
1807 	uint64_t	rxstat;
1808 	struct rxbuf	*newbufs;
1809 	struct rxbuf	**newbufs_tailp;
1810 	mblk_t		*rx_head;
1811 	mblk_t 		**rx_tailp;
1812 	int		rx_ring_size = dp->gc.gc_rx_ring_size;
1813 	seqnum_t	active_head;
1814 	uint64_t	(*rx_desc_stat)(struct gem_dev *dp,
1815 	    int slot, int ndesc);
1816 	int		ethermin = ETHERMIN;
1817 	int		ethermax = dp->mtu + sizeof (struct ether_header);
1818 	int		rx_header_len = dp->gc.gc_rx_header_len;
1819 
1820 	ASSERT(mutex_owned(&dp->intrlock));
1821 
1822 	DPRINTF(3, (CE_CONT, "!%s: gem_receive: rx_buf_head:%p",
1823 	    dp->name, dp->rx_buf_head));
1824 
1825 	rx_desc_stat  = dp->gc.gc_rx_desc_stat;
1826 	newbufs_tailp = &newbufs;
1827 	rx_tailp = &rx_head;
1828 	for (active_head = dp->rx_active_head;
1829 	    (rbp = dp->rx_buf_head) != NULL; active_head++) {
1830 		int		len;
1831 		if (cnt == 0) {
1832 			cnt = max(dp->poll_pkt_delay*2, 10);
1833 			cnt = min(cnt,
1834 			    dp->rx_active_tail - active_head);
1835 			gem_rx_desc_dma_sync(dp,
1836 			    SLOT(active_head, rx_ring_size),
1837 			    cnt,
1838 			    DDI_DMA_SYNC_FORKERNEL);
1839 		}
1840 
1841 		if (rx_header_len > 0) {
1842 			(void) ddi_dma_sync(rbp->rxb_dh, 0,
1843 			    rx_header_len, DDI_DMA_SYNC_FORKERNEL);
1844 		}
1845 
1846 		if (((rxstat = (*rx_desc_stat)(dp,
1847 		    SLOT(active_head, rx_ring_size),
1848 		    rbp->rxb_nfrags))
1849 		    & (GEM_RX_DONE | GEM_RX_ERR)) == 0) {
1850 			/* not received yet */
1851 			break;
1852 		}
1853 
1854 		/* Remove the head of the rx buffer list */
1855 		dp->rx_buf_head = rbp->rxb_next;
1856 		cnt--;
1857 
1858 
1859 		if (rxstat & GEM_RX_ERR) {
1860 			goto next;
1861 		}
1862 
1863 		len = rxstat & GEM_RX_LEN;
1864 		DPRINTF(3, (CE_CONT, "!%s: %s: rxstat:0x%llx, len:0x%x",
1865 		    dp->name, __func__, rxstat, len));
1866 
1867 		/*
1868 		 * Copy the packet
1869 		 */
1870 		if ((mp = dp->gc.gc_get_packet(dp, rbp, len)) == NULL) {
1871 			/* no memory, discard the packet */
1872 			dp->stats.norcvbuf++;
1873 			goto next;
1874 		}
1875 
1876 		/*
1877 		 * Process VLAN tag
1878 		 */
1879 		ethermin = ETHERMIN;
1880 		ethermax = dp->mtu + sizeof (struct ether_header);
1881 		if (GET_NET16(mp->b_rptr + VTAG_OFF) == VTAG_TPID) {
1882 			ethermax += VTAG_SIZE;
1883 		}
1884 
1885 		/* check packet size */
1886 		if (len < ethermin) {
1887 			dp->stats.errrcv++;
1888 			dp->stats.runt++;
1889 			freemsg(mp);
1890 			goto next;
1891 		}
1892 
1893 		if (len > ethermax) {
1894 			dp->stats.errrcv++;
1895 			dp->stats.frame_too_long++;
1896 			freemsg(mp);
1897 			goto next;
1898 		}
1899 
1900 		len_total += len;
1901 
1902 #ifdef GEM_DEBUG_VLAN
1903 		if (GET_ETHERTYPE(mp->b_rptr) == VTAG_TPID) {
1904 			gem_dump_packet(dp, (char *)__func__, mp, B_TRUE);
1905 		}
1906 #endif
1907 		/* append received packet to temporaly rx buffer list */
1908 		*rx_tailp = mp;
1909 		rx_tailp  = &mp->b_next;
1910 
1911 		if (mp->b_rptr[0] & 1) {
1912 			if (bcmp(mp->b_rptr,
1913 			    gem_etherbroadcastaddr.ether_addr_octet,
1914 			    ETHERADDRL) == 0) {
1915 				dp->stats.rbcast++;
1916 			} else {
1917 				dp->stats.rmcast++;
1918 			}
1919 		}
1920 next:
1921 		ASSERT(rbp != NULL);
1922 
1923 		/* append new one to temporal new buffer list */
1924 		*newbufs_tailp = rbp;
1925 		newbufs_tailp  = &rbp->rxb_next;
1926 	}
1927 
1928 	/* advance rx_active_head */
1929 	if ((cnt = active_head - dp->rx_active_head) > 0) {
1930 		dp->stats.rbytes += len_total;
1931 		dp->stats.rpackets += cnt;
1932 	}
1933 	dp->rx_active_head = active_head;
1934 
1935 	/* terminate the working list */
1936 	*newbufs_tailp = NULL;
1937 	*rx_tailp = NULL;
1938 
1939 	if (dp->rx_buf_head == NULL) {
1940 		dp->rx_buf_tail = NULL;
1941 	}
1942 
1943 	DPRINTF(4, (CE_CONT, "%s: %s: cnt:%d, rx_head:%p",
1944 	    dp->name, __func__, cnt, rx_head));
1945 
1946 	if (newbufs) {
1947 		/*
1948 		 * fillfull rx list with new buffers
1949 		 */
1950 		seqnum_t	head;
1951 
1952 		/* save current tail */
1953 		head = dp->rx_active_tail;
1954 		gem_append_rxbuf(dp, newbufs);
1955 
1956 		/* call hw depend start routine if we have. */
1957 		dp->gc.gc_rx_start(dp,
1958 		    SLOT(head, rx_ring_size), dp->rx_active_tail - head);
1959 	}
1960 
1961 	if (rx_head) {
1962 		/*
1963 		 * send up received packets
1964 		 */
1965 		mutex_exit(&dp->intrlock);
1966 		mac_rx(dp->mh, NULL, rx_head);
1967 		mutex_enter(&dp->intrlock);
1968 	}
1969 
1970 #ifdef GEM_DEBUG_LEVEL
1971 	gem_rx_pkts[min(cnt, sizeof (gem_rx_pkts)/sizeof (uint_t)-1)]++;
1972 #endif
1973 	return (cnt);
1974 }
1975 
1976 boolean_t
1977 gem_tx_done(struct gem_dev *dp)
1978 {
1979 	boolean_t	tx_sched = B_FALSE;
1980 
1981 	if (gem_reclaim_txbuf(dp) != GEM_SUCCESS) {
1982 		(void) gem_restart_nic(dp, GEM_RESTART_KEEP_BUF);
1983 		DPRINTF(2, (CE_CONT, "!%s: gem_tx_done: tx_desc: %d %d",
1984 		    dp->name, dp->tx_active_head, dp->tx_active_tail));
1985 		tx_sched = B_TRUE;
1986 		goto x;
1987 	}
1988 
1989 	mutex_enter(&dp->xmitlock);
1990 
1991 	/* XXX - we must not have any packets in soft queue */
1992 	ASSERT(dp->tx_softq_head == dp->tx_softq_tail);
1993 	/*
1994 	 * If we won't have chance to get more free tx buffers, and blocked,
1995 	 * it is worth to reschedule the downstream i.e. tx side.
1996 	 */
1997 	ASSERT(dp->tx_desc_intr - dp->tx_desc_head >= 0);
1998 	if (dp->tx_blocked && dp->tx_desc_intr == dp->tx_desc_head) {
1999 		/*
2000 		 * As no further tx-done interrupts are scheduled, this
2001 		 * is the last chance to kick tx side, which may be
2002 		 * blocked now, otherwise the tx side never works again.
2003 		 */
2004 		tx_sched = B_TRUE;
2005 		dp->tx_blocked = (clock_t)0;
2006 		dp->tx_max_packets =
2007 		    min(dp->tx_max_packets + 2, dp->gc.gc_tx_buf_limit);
2008 	}
2009 
2010 	mutex_exit(&dp->xmitlock);
2011 
2012 	DPRINTF(3, (CE_CONT, "!%s: %s: ret: blocked:%d",
2013 	    dp->name, __func__, BOOLEAN(dp->tx_blocked)));
2014 x:
2015 	return (tx_sched);
2016 }
2017 
2018 static uint_t
2019 gem_intr(struct gem_dev	*dp)
2020 {
2021 	uint_t		ret;
2022 
2023 	mutex_enter(&dp->intrlock);
2024 	if (dp->mac_suspended) {
2025 		mutex_exit(&dp->intrlock);
2026 		return (DDI_INTR_UNCLAIMED);
2027 	}
2028 	dp->intr_busy = B_TRUE;
2029 
2030 	ret = (*dp->gc.gc_interrupt)(dp);
2031 
2032 	if (ret == DDI_INTR_UNCLAIMED) {
2033 		dp->intr_busy = B_FALSE;
2034 		mutex_exit(&dp->intrlock);
2035 		return (ret);
2036 	}
2037 
2038 	if (!dp->mac_active) {
2039 		cv_broadcast(&dp->tx_drain_cv);
2040 	}
2041 
2042 
2043 	dp->stats.intr++;
2044 	dp->intr_busy = B_FALSE;
2045 
2046 	mutex_exit(&dp->intrlock);
2047 
2048 	if (ret & INTR_RESTART_TX) {
2049 		DPRINTF(4, (CE_CONT, "!%s: calling mac_tx_update", dp->name));
2050 		mac_tx_update(dp->mh);
2051 		ret &= ~INTR_RESTART_TX;
2052 	}
2053 	return (ret);
2054 }
2055 
2056 static void
2057 gem_intr_watcher(struct gem_dev *dp)
2058 {
2059 	(void) gem_intr(dp);
2060 
2061 	/* schedule next call of tu_intr_watcher */
2062 	dp->intr_watcher_id =
2063 	    timeout((void (*)(void *))gem_intr_watcher, (void *)dp, 1);
2064 }
2065 
2066 /* ======================================================================== */
2067 /*
2068  * MII support routines
2069  */
2070 /* ======================================================================== */
2071 static void
2072 gem_choose_forcedmode(struct gem_dev *dp)
2073 {
2074 	/* choose media mode */
2075 	if (dp->anadv_1000fdx || dp->anadv_1000hdx) {
2076 		dp->speed = GEM_SPD_1000;
2077 		dp->full_duplex = dp->anadv_1000fdx;
2078 	} else if (dp->anadv_100fdx || dp->anadv_100t4) {
2079 		dp->speed = GEM_SPD_100;
2080 		dp->full_duplex = B_TRUE;
2081 	} else if (dp->anadv_100hdx) {
2082 		dp->speed = GEM_SPD_100;
2083 		dp->full_duplex = B_FALSE;
2084 	} else {
2085 		dp->speed = GEM_SPD_10;
2086 		dp->full_duplex = dp->anadv_10fdx;
2087 	}
2088 }
2089 
2090 uint16_t
2091 gem_mii_read(struct gem_dev *dp, uint_t reg)
2092 {
2093 	if ((dp->mii_status & MII_STATUS_MFPRMBLSUPR) == 0) {
2094 		(*dp->gc.gc_mii_sync)(dp);
2095 	}
2096 	return ((*dp->gc.gc_mii_read)(dp, reg));
2097 }
2098 
2099 void
2100 gem_mii_write(struct gem_dev *dp, uint_t reg, uint16_t val)
2101 {
2102 	if ((dp->mii_status & MII_STATUS_MFPRMBLSUPR) == 0) {
2103 		(*dp->gc.gc_mii_sync)(dp);
2104 	}
2105 	(*dp->gc.gc_mii_write)(dp, reg, val);
2106 }
2107 
2108 #define	fc_cap_decode(x)	\
2109 	((((x) & MII_ABILITY_PAUSE) ? 1 : 0) |	\
2110 	(((x) & MII_ABILITY_ASMPAUSE) ? 2 : 0))
2111 
2112 int
2113 gem_mii_config_default(struct gem_dev *dp)
2114 {
2115 	uint16_t	mii_stat;
2116 	uint16_t	val;
2117 	static uint16_t fc_cap_encode[4] = {
2118 		0, /* none */
2119 		MII_ABILITY_PAUSE, /* symmetric */
2120 		MII_ABILITY_ASMPAUSE, /* tx */
2121 		MII_ABILITY_PAUSE | MII_ABILITY_ASMPAUSE, /* rx-symmetric */
2122 	};
2123 
2124 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2125 
2126 	/*
2127 	 * Configure bits in advertisement register
2128 	 */
2129 	mii_stat = dp->mii_status;
2130 
2131 	DPRINTF(1, (CE_CONT, "!%s: %s: MII_STATUS reg:%b",
2132 	    dp->name, __func__, mii_stat, MII_STATUS_BITS));
2133 
2134 	if ((mii_stat & MII_STATUS_ABILITY_TECH) == 0) {
2135 		/* it's funny */
2136 		cmn_err(CE_WARN, "!%s: wrong ability bits: mii_status:%b",
2137 		    dp->name, mii_stat, MII_STATUS_BITS);
2138 		return (GEM_FAILURE);
2139 	}
2140 
2141 	/* Do not change the rest of the ability bits in the advert reg */
2142 	val = gem_mii_read(dp, MII_AN_ADVERT) & ~MII_ABILITY_ALL;
2143 
2144 	DPRINTF(0, (CE_CONT,
2145 	    "!%s: %s: 100T4:%d 100F:%d 100H:%d 10F:%d 10H:%d",
2146 	    dp->name, __func__,
2147 	    dp->anadv_100t4, dp->anadv_100fdx, dp->anadv_100hdx,
2148 	    dp->anadv_10fdx, dp->anadv_10hdx));
2149 
2150 	if (dp->anadv_100t4) {
2151 		val |= MII_ABILITY_100BASE_T4;
2152 	}
2153 	if (dp->anadv_100fdx) {
2154 		val |= MII_ABILITY_100BASE_TX_FD;
2155 	}
2156 	if (dp->anadv_100hdx) {
2157 		val |= MII_ABILITY_100BASE_TX;
2158 	}
2159 	if (dp->anadv_10fdx) {
2160 		val |= MII_ABILITY_10BASE_T_FD;
2161 	}
2162 	if (dp->anadv_10hdx) {
2163 		val |= MII_ABILITY_10BASE_T;
2164 	}
2165 
2166 	/* set flow control capability */
2167 	val |= fc_cap_encode[dp->anadv_flow_control];
2168 
2169 	DPRINTF(0, (CE_CONT,
2170 	    "!%s: %s: setting MII_AN_ADVERT reg:%b, mii_mode:%d, fc:%d",
2171 	    dp->name, __func__, val, MII_ABILITY_BITS, dp->gc.gc_mii_mode,
2172 	    dp->anadv_flow_control));
2173 
2174 	gem_mii_write(dp, MII_AN_ADVERT, val);
2175 
2176 	if (mii_stat & MII_STATUS_XSTATUS) {
2177 		/*
2178 		 * 1000Base-T GMII support
2179 		 */
2180 		if (!dp->anadv_autoneg) {
2181 			/* enable manual configuration */
2182 			val = MII_1000TC_CFG_EN;
2183 		} else {
2184 			val = 0;
2185 			if (dp->anadv_1000fdx) {
2186 				val |= MII_1000TC_ADV_FULL;
2187 			}
2188 			if (dp->anadv_1000hdx) {
2189 				val |= MII_1000TC_ADV_HALF;
2190 			}
2191 		}
2192 		DPRINTF(0, (CE_CONT,
2193 		    "!%s: %s: setting MII_1000TC reg:%b",
2194 		    dp->name, __func__, val, MII_1000TC_BITS));
2195 
2196 		gem_mii_write(dp, MII_1000TC, val);
2197 	}
2198 
2199 	return (GEM_SUCCESS);
2200 }
2201 
2202 #define	GEM_LINKUP(dp)		mac_link_update((dp)->mh, LINK_STATE_UP)
2203 #define	GEM_LINKDOWN(dp)	mac_link_update((dp)->mh, LINK_STATE_DOWN)
2204 
2205 static uint8_t gem_fc_result[4 /* my cap */ ][4 /* lp cap */] = {
2206 /*	 none	symm	tx	rx/symm */
2207 /* none */
2208 	{FLOW_CONTROL_NONE,
2209 		FLOW_CONTROL_NONE,
2210 			FLOW_CONTROL_NONE,
2211 				FLOW_CONTROL_NONE},
2212 /* sym */
2213 	{FLOW_CONTROL_NONE,
2214 		FLOW_CONTROL_SYMMETRIC,
2215 			FLOW_CONTROL_NONE,
2216 				FLOW_CONTROL_SYMMETRIC},
2217 /* tx */
2218 	{FLOW_CONTROL_NONE,
2219 		FLOW_CONTROL_NONE,
2220 			FLOW_CONTROL_NONE,
2221 				FLOW_CONTROL_TX_PAUSE},
2222 /* rx/symm */
2223 	{FLOW_CONTROL_NONE,
2224 		FLOW_CONTROL_SYMMETRIC,
2225 			FLOW_CONTROL_RX_PAUSE,
2226 				FLOW_CONTROL_SYMMETRIC},
2227 };
2228 
2229 static char *gem_fc_type[] = {
2230 	"without",
2231 	"with symmetric",
2232 	"with tx",
2233 	"with rx",
2234 };
2235 
2236 boolean_t
2237 gem_mii_link_check(struct gem_dev *dp)
2238 {
2239 	uint16_t	old_mii_state;
2240 	boolean_t	tx_sched = B_FALSE;
2241 	uint16_t	status;
2242 	uint16_t	advert;
2243 	uint16_t	lpable;
2244 	uint16_t	exp;
2245 	uint16_t	ctl1000;
2246 	uint16_t	stat1000;
2247 	uint16_t	val;
2248 	clock_t		now;
2249 	clock_t		diff;
2250 	int		linkdown_action;
2251 	boolean_t	fix_phy = B_FALSE;
2252 
2253 	now = ddi_get_lbolt();
2254 	old_mii_state = dp->mii_state;
2255 
2256 	DPRINTF(3, (CE_CONT, "!%s: %s: time:%d state:%d",
2257 	    dp->name, __func__, now, dp->mii_state));
2258 
2259 	diff = now - dp->mii_last_check;
2260 	dp->mii_last_check = now;
2261 
2262 	/*
2263 	 * For NWAM, don't show linkdown state right
2264 	 * after the system boots
2265 	 */
2266 	if (dp->linkup_delay > 0) {
2267 		if (dp->linkup_delay > diff) {
2268 			dp->linkup_delay -= diff;
2269 		} else {
2270 			/* link up timeout */
2271 			dp->linkup_delay = -1;
2272 		}
2273 	}
2274 
2275 next_nowait:
2276 	switch (dp->mii_state) {
2277 	case MII_STATE_UNKNOWN:
2278 		/* power-up, DP83840 requires 32 sync bits */
2279 		(*dp->gc.gc_mii_sync)(dp);
2280 		goto reset_phy;
2281 
2282 	case MII_STATE_RESETTING:
2283 		dp->mii_timer -= diff;
2284 		if (dp->mii_timer > 0) {
2285 			/* don't read phy registers in resetting */
2286 			dp->mii_interval = WATCH_INTERVAL_FAST;
2287 			goto next;
2288 		}
2289 
2290 		/* Timer expired, ensure reset bit is not set */
2291 
2292 		if (dp->mii_status & MII_STATUS_MFPRMBLSUPR) {
2293 			/* some phys need sync bits after reset */
2294 			(*dp->gc.gc_mii_sync)(dp);
2295 		}
2296 		val = gem_mii_read(dp, MII_CONTROL);
2297 		if (val & MII_CONTROL_RESET) {
2298 			cmn_err(CE_NOTE,
2299 			    "!%s: time:%ld resetting phy not complete."
2300 			    " mii_control:0x%b",
2301 			    dp->name, ddi_get_lbolt(),
2302 			    val, MII_CONTROL_BITS);
2303 		}
2304 
2305 		/* ensure neither isolated nor pwrdown nor auto-nego mode */
2306 		/* XXX -- this operation is required for NS DP83840A. */
2307 		gem_mii_write(dp, MII_CONTROL, 0);
2308 
2309 		/* As resetting PHY has completed, configure PHY registers */
2310 		if ((*dp->gc.gc_mii_config)(dp) != GEM_SUCCESS) {
2311 			/* we failed to configure PHY. */
2312 			goto reset_phy;
2313 		}
2314 
2315 		/* mii_config may disable autonegatiation */
2316 		gem_choose_forcedmode(dp);
2317 
2318 		dp->mii_lpable = 0;
2319 		dp->mii_advert = 0;
2320 		dp->mii_exp = 0;
2321 		dp->mii_ctl1000 = 0;
2322 		dp->mii_stat1000 = 0;
2323 		dp->flow_control = FLOW_CONTROL_NONE;
2324 
2325 		if (!dp->anadv_autoneg) {
2326 			/* skip auto-negotiation phase */
2327 			dp->mii_state = MII_STATE_MEDIA_SETUP;
2328 			dp->mii_timer = 0;
2329 			dp->mii_interval = 0;
2330 			goto next_nowait;
2331 		}
2332 
2333 		/* Issue auto-negotiation command */
2334 		goto autonego;
2335 
2336 	case MII_STATE_AUTONEGOTIATING:
2337 		/*
2338 		 * Autonegotiation is in progress
2339 		 */
2340 		dp->mii_timer -= diff;
2341 		if (dp->mii_timer -
2342 		    (dp->gc.gc_mii_an_timeout
2343 		    - dp->gc.gc_mii_an_wait) > 0) {
2344 			/*
2345 			 * wait for a while, typically autonegotiation
2346 			 * completes in 2.3 - 2.5 sec.
2347 			 */
2348 			dp->mii_interval = WATCH_INTERVAL_FAST;
2349 			goto next;
2350 		}
2351 
2352 		/* read PHY status */
2353 		status = gem_mii_read(dp, MII_STATUS);
2354 		DPRINTF(4, (CE_CONT,
2355 		    "!%s: %s: called: mii_state:%d MII_STATUS reg:%b",
2356 		    dp->name, __func__, dp->mii_state,
2357 		    status, MII_STATUS_BITS));
2358 
2359 		if (status & MII_STATUS_REMFAULT) {
2360 			/*
2361 			 * The link parnert told me something wrong happend.
2362 			 * What do we do ?
2363 			 */
2364 			cmn_err(CE_CONT,
2365 			    "!%s: auto-negotiation failed: remote fault",
2366 			    dp->name);
2367 			goto autonego;
2368 		}
2369 
2370 		if ((status & MII_STATUS_ANDONE) == 0) {
2371 			if (dp->mii_timer <= 0) {
2372 				/*
2373 				 * Auto-negotiation was timed out,
2374 				 * try again w/o resetting phy.
2375 				 */
2376 				if (!dp->mii_supress_msg) {
2377 					cmn_err(CE_WARN,
2378 				    "!%s: auto-negotiation failed: timeout",
2379 					    dp->name);
2380 					dp->mii_supress_msg = B_TRUE;
2381 				}
2382 				goto autonego;
2383 			}
2384 			/*
2385 			 * Auto-negotiation is in progress. Wait.
2386 			 */
2387 			dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2388 			goto next;
2389 		}
2390 
2391 		/*
2392 		 * Auto-negotiation have completed.
2393 		 * Assume linkdown and fall through.
2394 		 */
2395 		dp->mii_supress_msg = B_FALSE;
2396 		dp->mii_state = MII_STATE_AN_DONE;
2397 		DPRINTF(0, (CE_CONT,
2398 		    "!%s: auto-negotiation completed, MII_STATUS:%b",
2399 		    dp->name, status, MII_STATUS_BITS));
2400 
2401 		if (dp->gc.gc_mii_an_delay > 0) {
2402 			dp->mii_timer = dp->gc.gc_mii_an_delay;
2403 			dp->mii_interval = drv_usectohz(20*1000);
2404 			goto next;
2405 		}
2406 
2407 		dp->mii_timer = 0;
2408 		diff = 0;
2409 		goto next_nowait;
2410 
2411 	case MII_STATE_AN_DONE:
2412 		/*
2413 		 * Auto-negotiation have done. Now we can set up media.
2414 		 */
2415 		dp->mii_timer -= diff;
2416 		if (dp->mii_timer > 0) {
2417 			/* wait for a while */
2418 			dp->mii_interval = WATCH_INTERVAL_FAST;
2419 			goto next;
2420 		}
2421 
2422 		/*
2423 		 * set up the result of auto negotiation
2424 		 */
2425 
2426 		/*
2427 		 * Read registers required to determin current
2428 		 * duplex mode and media speed.
2429 		 */
2430 		if (dp->gc.gc_mii_an_delay > 0) {
2431 			/*
2432 			 * As the link watcher context has been suspended,
2433 			 * 'status' is invalid. We must status register here
2434 			 */
2435 			status = gem_mii_read(dp, MII_STATUS);
2436 		}
2437 		advert = gem_mii_read(dp, MII_AN_ADVERT);
2438 		lpable = gem_mii_read(dp, MII_AN_LPABLE);
2439 		exp = gem_mii_read(dp, MII_AN_EXPANSION);
2440 		if (exp == 0xffff) {
2441 			/* some phys don't have exp register */
2442 			exp = 0;
2443 		}
2444 		ctl1000  = 0;
2445 		stat1000 = 0;
2446 		if (dp->mii_status & MII_STATUS_XSTATUS) {
2447 			ctl1000  = gem_mii_read(dp, MII_1000TC);
2448 			stat1000 = gem_mii_read(dp, MII_1000TS);
2449 		}
2450 		dp->mii_lpable = lpable;
2451 		dp->mii_advert = advert;
2452 		dp->mii_exp = exp;
2453 		dp->mii_ctl1000  = ctl1000;
2454 		dp->mii_stat1000 = stat1000;
2455 
2456 		cmn_err(CE_CONT,
2457 		"!%s: auto-negotiation done, advert:%b, lpable:%b, exp:%b",
2458 		    dp->name,
2459 		    advert, MII_ABILITY_BITS,
2460 		    lpable, MII_ABILITY_BITS,
2461 		    exp, MII_AN_EXP_BITS);
2462 
2463 		if (dp->mii_status & MII_STATUS_XSTATUS) {
2464 			cmn_err(CE_CONT,
2465 			    "! MII_1000TC:%b, MII_1000TS:%b",
2466 			    ctl1000, MII_1000TC_BITS,
2467 			    stat1000, MII_1000TS_BITS);
2468 		}
2469 
2470 		if (gem_population(lpable) <= 1 &&
2471 		    (exp & MII_AN_EXP_LPCANAN) == 0) {
2472 			if ((advert & MII_ABILITY_TECH) != lpable) {
2473 				cmn_err(CE_WARN,
2474 				    "!%s: but the link partnar doesn't seem"
2475 				    " to have auto-negotiation capability."
2476 				    " please check the link configuration.",
2477 				    dp->name);
2478 			}
2479 			/*
2480 			 * it should be result of parallel detection, which
2481 			 * cannot detect duplex mode.
2482 			 */
2483 			if (lpable & MII_ABILITY_100BASE_TX) {
2484 				/*
2485 				 * we prefer full duplex mode for 100Mbps
2486 				 * connection, if we can.
2487 				 */
2488 				lpable |= advert & MII_ABILITY_100BASE_TX_FD;
2489 			}
2490 
2491 			if ((advert & lpable) == 0 &&
2492 			    lpable & MII_ABILITY_10BASE_T) {
2493 				lpable |= advert & MII_ABILITY_10BASE_T_FD;
2494 			}
2495 			/*
2496 			 * as the link partnar isn't auto-negotiatable, use
2497 			 * fixed mode temporally.
2498 			 */
2499 			fix_phy = B_TRUE;
2500 		} else if (lpable == 0) {
2501 			cmn_err(CE_WARN, "!%s: wrong lpable.", dp->name);
2502 			goto reset_phy;
2503 		}
2504 		/*
2505 		 * configure current link mode according to AN priority.
2506 		 */
2507 		val = advert & lpable;
2508 		if ((ctl1000 & MII_1000TC_ADV_FULL) &&
2509 		    (stat1000 & MII_1000TS_LP_FULL)) {
2510 			/* 1000BaseT & full duplex */
2511 			dp->speed	 = GEM_SPD_1000;
2512 			dp->full_duplex  = B_TRUE;
2513 		} else if ((ctl1000 & MII_1000TC_ADV_HALF) &&
2514 		    (stat1000 & MII_1000TS_LP_HALF)) {
2515 			/* 1000BaseT & half duplex */
2516 			dp->speed = GEM_SPD_1000;
2517 			dp->full_duplex = B_FALSE;
2518 		} else if (val & MII_ABILITY_100BASE_TX_FD) {
2519 			/* 100BaseTx & full duplex */
2520 			dp->speed = GEM_SPD_100;
2521 			dp->full_duplex = B_TRUE;
2522 		} else if (val & MII_ABILITY_100BASE_T4) {
2523 			/* 100BaseT4 & full duplex */
2524 			dp->speed = GEM_SPD_100;
2525 			dp->full_duplex = B_TRUE;
2526 		} else if (val & MII_ABILITY_100BASE_TX) {
2527 			/* 100BaseTx & half duplex */
2528 			dp->speed	 = GEM_SPD_100;
2529 			dp->full_duplex  = B_FALSE;
2530 		} else if (val & MII_ABILITY_10BASE_T_FD) {
2531 			/* 10BaseT & full duplex */
2532 			dp->speed	 = GEM_SPD_10;
2533 			dp->full_duplex  = B_TRUE;
2534 		} else if (val & MII_ABILITY_10BASE_T) {
2535 			/* 10BaseT & half duplex */
2536 			dp->speed	 = GEM_SPD_10;
2537 			dp->full_duplex  = B_FALSE;
2538 		} else {
2539 			/*
2540 			 * It seems that the link partnar doesn't have
2541 			 * auto-negotiation capability and our PHY
2542 			 * could not report the correct current mode.
2543 			 * We guess current mode by mii_control register.
2544 			 */
2545 			val = gem_mii_read(dp, MII_CONTROL);
2546 
2547 			/* select 100m full or 10m half */
2548 			dp->speed = (val & MII_CONTROL_100MB) ?
2549 			    GEM_SPD_100 : GEM_SPD_10;
2550 			dp->full_duplex = dp->speed != GEM_SPD_10;
2551 			fix_phy = B_TRUE;
2552 
2553 			cmn_err(CE_NOTE,
2554 			    "!%s: auto-negotiation done but "
2555 			    "common ability not found.\n"
2556 			    "PHY state: control:%b advert:%b lpable:%b\n"
2557 			    "guessing %d Mbps %s duplex mode",
2558 			    dp->name,
2559 			    val, MII_CONTROL_BITS,
2560 			    advert, MII_ABILITY_BITS,
2561 			    lpable, MII_ABILITY_BITS,
2562 			    gem_speed_value[dp->speed],
2563 			    dp->full_duplex ? "full" : "half");
2564 		}
2565 
2566 		if (dp->full_duplex) {
2567 			dp->flow_control =
2568 			    gem_fc_result[fc_cap_decode(advert)]
2569 			    [fc_cap_decode(lpable)];
2570 		} else {
2571 			dp->flow_control = FLOW_CONTROL_NONE;
2572 		}
2573 		dp->mii_state = MII_STATE_MEDIA_SETUP;
2574 		/* FALLTHROUGH */
2575 
2576 	case MII_STATE_MEDIA_SETUP:
2577 		dp->mii_state = MII_STATE_LINKDOWN;
2578 		dp->mii_timer = dp->gc.gc_mii_linkdown_timeout;
2579 		DPRINTF(2, (CE_CONT, "!%s: setup midia mode done", dp->name));
2580 		dp->mii_supress_msg = B_FALSE;
2581 
2582 		/* use short interval */
2583 		dp->mii_interval = WATCH_INTERVAL_FAST;
2584 
2585 		if ((!dp->anadv_autoneg) ||
2586 		    dp->gc.gc_mii_an_oneshot || fix_phy) {
2587 
2588 			/*
2589 			 * write specified mode to phy.
2590 			 */
2591 			val = gem_mii_read(dp, MII_CONTROL);
2592 			val &= ~(MII_CONTROL_SPEED | MII_CONTROL_FDUPLEX |
2593 			    MII_CONTROL_ANE | MII_CONTROL_RSAN);
2594 
2595 			if (dp->full_duplex) {
2596 				val |= MII_CONTROL_FDUPLEX;
2597 			}
2598 
2599 			switch (dp->speed) {
2600 			case GEM_SPD_1000:
2601 				val |= MII_CONTROL_1000MB;
2602 				break;
2603 
2604 			case GEM_SPD_100:
2605 				val |= MII_CONTROL_100MB;
2606 				break;
2607 
2608 			default:
2609 				cmn_err(CE_WARN, "%s: unknown speed:%d",
2610 				    dp->name, dp->speed);
2611 				/* FALLTHROUGH */
2612 			case GEM_SPD_10:
2613 				/* for GEM_SPD_10, do nothing */
2614 				break;
2615 			}
2616 
2617 			if (dp->mii_status & MII_STATUS_XSTATUS) {
2618 				gem_mii_write(dp,
2619 				    MII_1000TC, MII_1000TC_CFG_EN);
2620 			}
2621 			gem_mii_write(dp, MII_CONTROL, val);
2622 		}
2623 
2624 		if (dp->nic_state >= NIC_STATE_INITIALIZED) {
2625 			/* notify the result of auto-negotiation to mac */
2626 			(*dp->gc.gc_set_media)(dp);
2627 		}
2628 
2629 		if ((void *)dp->gc.gc_mii_tune_phy) {
2630 			/* for built-in sis900 */
2631 			/* XXX - this code should be removed.  */
2632 			(*dp->gc.gc_mii_tune_phy)(dp);
2633 		}
2634 
2635 		goto next_nowait;
2636 
2637 	case MII_STATE_LINKDOWN:
2638 		status = gem_mii_read(dp, MII_STATUS);
2639 		if (status & MII_STATUS_LINKUP) {
2640 			/*
2641 			 * Link going up
2642 			 */
2643 			dp->mii_state = MII_STATE_LINKUP;
2644 			dp->mii_supress_msg = B_FALSE;
2645 
2646 			DPRINTF(0, (CE_CONT,
2647 			    "!%s: link up detected: mii_stat:%b",
2648 			    dp->name, status, MII_STATUS_BITS));
2649 
2650 			/*
2651 			 * MII_CONTROL_100MB and  MII_CONTROL_FDUPLEX are
2652 			 * ignored when MII_CONTROL_ANE is set.
2653 			 */
2654 			cmn_err(CE_CONT,
2655 			    "!%s: Link up: %d Mbps %s duplex %s flow control",
2656 			    dp->name,
2657 			    gem_speed_value[dp->speed],
2658 			    dp->full_duplex ? "full" : "half",
2659 			    gem_fc_type[dp->flow_control]);
2660 
2661 			dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2662 
2663 			/* XXX - we need other timer to watch statictics */
2664 			if (dp->gc.gc_mii_hw_link_detection &&
2665 			    dp->nic_state == NIC_STATE_ONLINE) {
2666 				dp->mii_interval = 0;
2667 			}
2668 
2669 			if (dp->nic_state == NIC_STATE_ONLINE) {
2670 				if (!dp->mac_active) {
2671 					(void) gem_mac_start(dp);
2672 				}
2673 				tx_sched = B_TRUE;
2674 			}
2675 			goto next;
2676 		}
2677 
2678 		dp->mii_supress_msg = B_TRUE;
2679 		if (dp->anadv_autoneg) {
2680 			dp->mii_timer -= diff;
2681 			if (dp->mii_timer <= 0) {
2682 				/*
2683 				 * link down timer expired.
2684 				 * need to restart auto-negotiation.
2685 				 */
2686 				linkdown_action =
2687 				    dp->gc.gc_mii_linkdown_timeout_action;
2688 				goto restart_autonego;
2689 			}
2690 		}
2691 		/* don't change mii_state */
2692 		break;
2693 
2694 	case MII_STATE_LINKUP:
2695 		status = gem_mii_read(dp, MII_STATUS);
2696 		if ((status & MII_STATUS_LINKUP) == 0) {
2697 			/*
2698 			 * Link going down
2699 			 */
2700 			cmn_err(CE_NOTE,
2701 			    "!%s: link down detected: mii_stat:%b",
2702 			    dp->name, status, MII_STATUS_BITS);
2703 
2704 			if (dp->nic_state == NIC_STATE_ONLINE &&
2705 			    dp->mac_active &&
2706 			    dp->gc.gc_mii_stop_mac_on_linkdown) {
2707 				(void) gem_mac_stop(dp, 0);
2708 
2709 				if (dp->tx_blocked) {
2710 					/* drain tx */
2711 					tx_sched = B_TRUE;
2712 				}
2713 			}
2714 
2715 			if (dp->anadv_autoneg) {
2716 				/* need to restart auto-negotiation */
2717 				linkdown_action = dp->gc.gc_mii_linkdown_action;
2718 				goto restart_autonego;
2719 			}
2720 
2721 			dp->mii_state = MII_STATE_LINKDOWN;
2722 			dp->mii_timer = dp->gc.gc_mii_linkdown_timeout;
2723 
2724 			if ((void *)dp->gc.gc_mii_tune_phy) {
2725 				/* for built-in sis900 */
2726 				(*dp->gc.gc_mii_tune_phy)(dp);
2727 			}
2728 			dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2729 			goto next;
2730 		}
2731 
2732 		/* don't change mii_state */
2733 		if (dp->gc.gc_mii_hw_link_detection &&
2734 		    dp->nic_state == NIC_STATE_ONLINE) {
2735 			dp->mii_interval = 0;
2736 			goto next;
2737 		}
2738 		break;
2739 	}
2740 	dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2741 	goto next;
2742 
2743 	/* Actions on the end of state routine */
2744 
2745 restart_autonego:
2746 	switch (linkdown_action) {
2747 	case MII_ACTION_RESET:
2748 		if (!dp->mii_supress_msg) {
2749 			cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
2750 		}
2751 		dp->mii_supress_msg = B_TRUE;
2752 		goto reset_phy;
2753 
2754 	case MII_ACTION_NONE:
2755 		dp->mii_supress_msg = B_TRUE;
2756 		if (dp->gc.gc_mii_an_oneshot) {
2757 			goto autonego;
2758 		}
2759 		/* PHY will restart autonego automatically */
2760 		dp->mii_state = MII_STATE_AUTONEGOTIATING;
2761 		dp->mii_timer = dp->gc.gc_mii_an_timeout;
2762 		dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2763 		goto next;
2764 
2765 	case MII_ACTION_RSA:
2766 		if (!dp->mii_supress_msg) {
2767 			cmn_err(CE_CONT, "!%s: restarting auto-negotiation",
2768 			    dp->name);
2769 		}
2770 		dp->mii_supress_msg = B_TRUE;
2771 		goto autonego;
2772 
2773 	default:
2774 		cmn_err(CE_WARN, "!%s: unknowm linkdown action: %d",
2775 		    dp->name, dp->gc.gc_mii_linkdown_action);
2776 		dp->mii_supress_msg = B_TRUE;
2777 	}
2778 	/* NOTREACHED */
2779 
2780 reset_phy:
2781 	if (!dp->mii_supress_msg) {
2782 		cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
2783 	}
2784 	dp->mii_state = MII_STATE_RESETTING;
2785 	dp->mii_timer = dp->gc.gc_mii_reset_timeout;
2786 	if (!dp->gc.gc_mii_dont_reset) {
2787 		gem_mii_write(dp, MII_CONTROL, MII_CONTROL_RESET);
2788 	}
2789 	dp->mii_interval = WATCH_INTERVAL_FAST;
2790 	goto next;
2791 
2792 autonego:
2793 	if (!dp->mii_supress_msg) {
2794 		cmn_err(CE_CONT, "!%s: auto-negotiation started", dp->name);
2795 	}
2796 	dp->mii_state = MII_STATE_AUTONEGOTIATING;
2797 	dp->mii_timer = dp->gc.gc_mii_an_timeout;
2798 
2799 	/* start/restart auto nego */
2800 	val = gem_mii_read(dp, MII_CONTROL) &
2801 	    ~(MII_CONTROL_ISOLATE | MII_CONTROL_PWRDN | MII_CONTROL_RESET);
2802 
2803 	gem_mii_write(dp, MII_CONTROL,
2804 	    val | MII_CONTROL_RSAN | MII_CONTROL_ANE);
2805 
2806 	dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2807 
2808 next:
2809 	if (dp->link_watcher_id == 0 && dp->mii_interval) {
2810 		/* we must schedule next mii_watcher */
2811 		dp->link_watcher_id =
2812 		    timeout((void (*)(void *))&gem_mii_link_watcher,
2813 		    (void *)dp, dp->mii_interval);
2814 	}
2815 
2816 	if (old_mii_state != dp->mii_state) {
2817 		/* notify new mii link state */
2818 		if (dp->mii_state == MII_STATE_LINKUP) {
2819 			dp->linkup_delay = 0;
2820 			GEM_LINKUP(dp);
2821 		} else if (dp->linkup_delay <= 0) {
2822 			GEM_LINKDOWN(dp);
2823 		}
2824 	} else if (dp->linkup_delay < 0) {
2825 		/* first linkup timeout */
2826 		dp->linkup_delay = 0;
2827 		GEM_LINKDOWN(dp);
2828 	}
2829 
2830 	return (tx_sched);
2831 }
2832 
2833 static void
2834 gem_mii_link_watcher(struct gem_dev *dp)
2835 {
2836 	boolean_t	tx_sched;
2837 
2838 	mutex_enter(&dp->intrlock);
2839 
2840 	dp->link_watcher_id = 0;
2841 	tx_sched = gem_mii_link_check(dp);
2842 #if GEM_DEBUG_LEVEL > 2
2843 	if (dp->link_watcher_id == 0) {
2844 		cmn_err(CE_CONT, "%s: link watcher stopped", dp->name);
2845 	}
2846 #endif
2847 	mutex_exit(&dp->intrlock);
2848 
2849 	if (tx_sched) {
2850 		/* kick potentially stopped downstream */
2851 		mac_tx_update(dp->mh);
2852 	}
2853 }
2854 
2855 int
2856 gem_mii_probe_default(struct gem_dev *dp)
2857 {
2858 	int8_t		phy;
2859 	uint16_t	status;
2860 	uint16_t	adv;
2861 	uint16_t	adv_org;
2862 
2863 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2864 
2865 	/*
2866 	 * Scan PHY
2867 	 */
2868 	/* ensure to send sync bits */
2869 	dp->mii_status = 0;
2870 
2871 	/* Try default phy first */
2872 	if (dp->mii_phy_addr) {
2873 		status = gem_mii_read(dp, MII_STATUS);
2874 		if (status != 0xffff && status != 0) {
2875 			gem_mii_write(dp, MII_CONTROL, 0);
2876 			goto PHY_found;
2877 		}
2878 
2879 		if (dp->mii_phy_addr < 0) {
2880 			cmn_err(CE_NOTE,
2881 	    "!%s: failed to probe default internal and/or non-MII PHY",
2882 			    dp->name);
2883 			return (GEM_FAILURE);
2884 		}
2885 
2886 		cmn_err(CE_NOTE,
2887 		    "!%s: failed to probe default MII PHY at %d",
2888 		    dp->name, dp->mii_phy_addr);
2889 	}
2890 
2891 	/* Try all possible address */
2892 	for (phy = dp->gc.gc_mii_addr_min; phy < 32; phy++) {
2893 		dp->mii_phy_addr = phy;
2894 		status = gem_mii_read(dp, MII_STATUS);
2895 
2896 		if (status != 0xffff && status != 0) {
2897 			gem_mii_write(dp, MII_CONTROL, 0);
2898 			goto PHY_found;
2899 		}
2900 	}
2901 
2902 	for (phy = dp->gc.gc_mii_addr_min; phy < 32; phy++) {
2903 		dp->mii_phy_addr = phy;
2904 		gem_mii_write(dp, MII_CONTROL, 0);
2905 		status = gem_mii_read(dp, MII_STATUS);
2906 
2907 		if (status != 0xffff && status != 0) {
2908 			goto PHY_found;
2909 		}
2910 	}
2911 
2912 	cmn_err(CE_NOTE, "!%s: no MII PHY found", dp->name);
2913 	dp->mii_phy_addr = -1;
2914 
2915 	return (GEM_FAILURE);
2916 
2917 PHY_found:
2918 	dp->mii_status = status;
2919 	dp->mii_phy_id  = (gem_mii_read(dp, MII_PHYIDH) << 16) |
2920 	    gem_mii_read(dp, MII_PHYIDL);
2921 
2922 	if (dp->mii_phy_addr < 0) {
2923 		cmn_err(CE_CONT, "!%s: using internal/non-MII PHY(0x%08x)",
2924 		    dp->name, dp->mii_phy_id);
2925 	} else {
2926 		cmn_err(CE_CONT, "!%s: MII PHY (0x%08x) found at %d",
2927 		    dp->name, dp->mii_phy_id, dp->mii_phy_addr);
2928 	}
2929 
2930 	cmn_err(CE_CONT, "!%s: PHY control:%b, status:%b, advert:%b, lpar:%b",
2931 	    dp->name,
2932 	    gem_mii_read(dp, MII_CONTROL), MII_CONTROL_BITS,
2933 	    status, MII_STATUS_BITS,
2934 	    gem_mii_read(dp, MII_AN_ADVERT), MII_ABILITY_BITS,
2935 	    gem_mii_read(dp, MII_AN_LPABLE), MII_ABILITY_BITS);
2936 
2937 	dp->mii_xstatus = 0;
2938 	if (status & MII_STATUS_XSTATUS) {
2939 		dp->mii_xstatus = gem_mii_read(dp, MII_XSTATUS);
2940 
2941 		cmn_err(CE_CONT, "!%s: xstatus:%b",
2942 		    dp->name, dp->mii_xstatus, MII_XSTATUS_BITS);
2943 	}
2944 
2945 	/* check if the phy can advertize pause abilities */
2946 	adv_org = gem_mii_read(dp, MII_AN_ADVERT);
2947 
2948 	gem_mii_write(dp, MII_AN_ADVERT,
2949 	    MII_ABILITY_PAUSE | MII_ABILITY_ASMPAUSE);
2950 
2951 	adv = gem_mii_read(dp, MII_AN_ADVERT);
2952 
2953 	if ((adv & MII_ABILITY_PAUSE) == 0) {
2954 		dp->gc.gc_flow_control &= ~1;
2955 	}
2956 
2957 	if ((adv & MII_ABILITY_ASMPAUSE) == 0) {
2958 		dp->gc.gc_flow_control &= ~2;
2959 	}
2960 
2961 	gem_mii_write(dp, MII_AN_ADVERT, adv_org);
2962 
2963 	return (GEM_SUCCESS);
2964 }
2965 
2966 static void
2967 gem_mii_start(struct gem_dev *dp)
2968 {
2969 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2970 
2971 	/* make a first call of check link */
2972 	dp->mii_state = MII_STATE_UNKNOWN;
2973 	dp->mii_last_check = ddi_get_lbolt();
2974 	dp->linkup_delay = dp->gc.gc_mii_linkdown_timeout;
2975 	(void) gem_mii_link_watcher(dp);
2976 }
2977 
2978 static void
2979 gem_mii_stop(struct gem_dev *dp)
2980 {
2981 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2982 
2983 	/* Ensure timer routine stopped */
2984 	mutex_enter(&dp->intrlock);
2985 	if (dp->link_watcher_id) {
2986 		while (untimeout(dp->link_watcher_id) == -1)
2987 			;
2988 		dp->link_watcher_id = 0;
2989 	}
2990 	mutex_exit(&dp->intrlock);
2991 }
2992 
2993 boolean_t
2994 gem_get_mac_addr_conf(struct gem_dev *dp)
2995 {
2996 	char		propname[32];
2997 	char		*valstr;
2998 	uint8_t		mac[ETHERADDRL];
2999 	char		*cp;
3000 	int		c;
3001 	int		i;
3002 	int		j;
3003 	uint8_t		v;
3004 	uint8_t		d;
3005 	uint8_t		ored;
3006 
3007 	DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3008 	/*
3009 	 * Get ethernet address from .conf file
3010 	 */
3011 	(void) sprintf(propname, "mac-addr");
3012 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dp->dip,
3013 	    DDI_PROP_DONTPASS, propname, &valstr)) !=
3014 	    DDI_PROP_SUCCESS) {
3015 		return (B_FALSE);
3016 	}
3017 
3018 	if (strlen(valstr) != ETHERADDRL*3-1) {
3019 		goto syntax_err;
3020 	}
3021 
3022 	cp = valstr;
3023 	j  = 0;
3024 	ored = 0;
3025 	for (;;) {
3026 		v = 0;
3027 		for (i = 0; i < 2; i++) {
3028 			c = *cp++;
3029 
3030 			if (c >= 'a' && c <= 'f') {
3031 				d = c - 'a' + 10;
3032 			} else if (c >= 'A' && c <= 'F') {
3033 				d = c - 'A' + 10;
3034 			} else if (c >= '0' && c <= '9') {
3035 				d = c - '0';
3036 			} else {
3037 				goto syntax_err;
3038 			}
3039 			v = (v << 4) | d;
3040 		}
3041 
3042 		mac[j++] = v;
3043 		ored |= v;
3044 		if (j == ETHERADDRL) {
3045 			/* done */
3046 			break;
3047 		}
3048 
3049 		c = *cp++;
3050 		if (c != ':') {
3051 			goto syntax_err;
3052 		}
3053 	}
3054 
3055 	if (ored == 0) {
3056 		goto err;
3057 	}
3058 	for (i = 0; i < ETHERADDRL; i++) {
3059 		dp->dev_addr.ether_addr_octet[i] = mac[i];
3060 	}
3061 	ddi_prop_free(valstr);
3062 	return (B_TRUE);
3063 
3064 syntax_err:
3065 	cmn_err(CE_CONT,
3066 	    "!%s: read mac addr: trying .conf: syntax err %s",
3067 	    dp->name, valstr);
3068 err:
3069 	ddi_prop_free(valstr);
3070 
3071 	return (B_FALSE);
3072 }
3073 
3074 
3075 /* ============================================================== */
3076 /*
3077  * internal start/stop interface
3078  */
3079 /* ============================================================== */
3080 static int
3081 gem_mac_set_rx_filter(struct gem_dev *dp)
3082 {
3083 	return ((*dp->gc.gc_set_rx_filter)(dp));
3084 }
3085 
3086 /*
3087  * gem_mac_init: cold start
3088  */
3089 static int
3090 gem_mac_init(struct gem_dev *dp)
3091 {
3092 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3093 
3094 	if (dp->mac_suspended) {
3095 		return (GEM_FAILURE);
3096 	}
3097 
3098 	dp->mac_active = B_FALSE;
3099 
3100 	gem_init_rx_ring(dp);
3101 	gem_init_tx_ring(dp);
3102 
3103 	/* reset transmitter state */
3104 	dp->tx_blocked = (clock_t)0;
3105 	dp->tx_busy = 0;
3106 	dp->tx_reclaim_busy = 0;
3107 	dp->tx_max_packets = dp->gc.gc_tx_buf_limit;
3108 
3109 	if ((*dp->gc.gc_init_chip)(dp) != GEM_SUCCESS) {
3110 		return (GEM_FAILURE);
3111 	}
3112 
3113 	gem_prepare_rx_buf(dp);
3114 
3115 	return (GEM_SUCCESS);
3116 }
3117 /*
3118  * gem_mac_start: warm start
3119  */
3120 static int
3121 gem_mac_start(struct gem_dev *dp)
3122 {
3123 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3124 
3125 	ASSERT(mutex_owned(&dp->intrlock));
3126 	ASSERT(dp->nic_state == NIC_STATE_ONLINE);
3127 	ASSERT(dp->mii_state ==  MII_STATE_LINKUP);
3128 
3129 	/* enable tx and rx */
3130 	mutex_enter(&dp->xmitlock);
3131 	if (dp->mac_suspended) {
3132 		mutex_exit(&dp->xmitlock);
3133 		return (GEM_FAILURE);
3134 	}
3135 	dp->mac_active = B_TRUE;
3136 	mutex_exit(&dp->xmitlock);
3137 
3138 	/* setup rx buffers */
3139 	(*dp->gc.gc_rx_start)(dp,
3140 	    SLOT(dp->rx_active_head, dp->gc.gc_rx_ring_size),
3141 	    dp->rx_active_tail - dp->rx_active_head);
3142 
3143 	if ((*dp->gc.gc_start_chip)(dp) != GEM_SUCCESS) {
3144 		cmn_err(CE_WARN, "%s: %s: start_chip: failed",
3145 		    dp->name, __func__);
3146 		return (GEM_FAILURE);
3147 	}
3148 
3149 	mutex_enter(&dp->xmitlock);
3150 
3151 	/* load untranmitted packets to the nic */
3152 	ASSERT(dp->tx_softq_tail - dp->tx_softq_head >= 0);
3153 	if (dp->tx_softq_tail - dp->tx_softq_head > 0) {
3154 		gem_tx_load_descs_oo(dp,
3155 		    dp->tx_softq_head, dp->tx_softq_tail,
3156 		    GEM_TXFLAG_HEAD);
3157 		/* issue preloaded tx buffers */
3158 		gem_tx_start_unit(dp);
3159 	}
3160 
3161 	mutex_exit(&dp->xmitlock);
3162 
3163 	return (GEM_SUCCESS);
3164 }
3165 
3166 static int
3167 gem_mac_stop(struct gem_dev *dp, uint_t flags)
3168 {
3169 	int		i;
3170 	int		wait_time; /* in uS */
3171 #ifdef GEM_DEBUG_LEVEL
3172 	clock_t		now;
3173 #endif
3174 	int		ret = GEM_SUCCESS;
3175 
3176 	DPRINTF(1, (CE_CONT, "!%s: %s: called, rx_buf_free:%d",
3177 	    dp->name, __func__, dp->rx_buf_freecnt));
3178 
3179 	ASSERT(mutex_owned(&dp->intrlock));
3180 	ASSERT(!mutex_owned(&dp->xmitlock));
3181 
3182 	/*
3183 	 * Block transmits
3184 	 */
3185 	mutex_enter(&dp->xmitlock);
3186 	if (dp->mac_suspended) {
3187 		mutex_exit(&dp->xmitlock);
3188 		return (GEM_SUCCESS);
3189 	}
3190 	dp->mac_active = B_FALSE;
3191 
3192 	while (dp->tx_busy > 0) {
3193 		cv_wait(&dp->tx_drain_cv, &dp->xmitlock);
3194 	}
3195 	mutex_exit(&dp->xmitlock);
3196 
3197 	if ((flags & GEM_RESTART_NOWAIT) == 0) {
3198 		/*
3199 		 * Wait for all tx buffers sent.
3200 		 */
3201 		wait_time =
3202 		    2 * (8 * MAXPKTBUF(dp) / gem_speed_value[dp->speed]) *
3203 		    (dp->tx_active_tail - dp->tx_active_head);
3204 
3205 		DPRINTF(0, (CE_CONT, "%s: %s: max drain time: %d uS",
3206 		    dp->name, __func__, wait_time));
3207 		i = 0;
3208 #ifdef GEM_DEBUG_LEVEL
3209 		now = ddi_get_lbolt();
3210 #endif
3211 		while (dp->tx_active_tail != dp->tx_active_head) {
3212 			if (i > wait_time) {
3213 				/* timeout */
3214 				cmn_err(CE_NOTE, "%s: %s timeout: tx drain",
3215 				    dp->name, __func__);
3216 				break;
3217 			}
3218 			(void) gem_reclaim_txbuf(dp);
3219 			drv_usecwait(100);
3220 			i += 100;
3221 		}
3222 		DPRINTF(0, (CE_NOTE,
3223 		    "!%s: %s: the nic have drained in %d uS, real %d mS",
3224 		    dp->name, __func__, i,
3225 		    10*((int)(ddi_get_lbolt() - now))));
3226 	}
3227 
3228 	/*
3229 	 * Now we can stop the nic safely.
3230 	 */
3231 	if ((*dp->gc.gc_stop_chip)(dp) != GEM_SUCCESS) {
3232 		cmn_err(CE_NOTE, "%s: %s: resetting the chip to stop it",
3233 		    dp->name, __func__);
3234 		if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
3235 			cmn_err(CE_WARN, "%s: %s: failed to reset chip",
3236 			    dp->name, __func__);
3237 		}
3238 	}
3239 
3240 	/*
3241 	 * Clear all rx buffers
3242 	 */
3243 	if (flags & GEM_RESTART_KEEP_BUF) {
3244 		(void) gem_receive(dp);
3245 	}
3246 	gem_clean_rx_buf(dp);
3247 
3248 	/*
3249 	 * Update final statistics
3250 	 */
3251 	(*dp->gc.gc_get_stats)(dp);
3252 
3253 	/*
3254 	 * Clear all pended tx packets
3255 	 */
3256 	ASSERT(dp->tx_active_tail == dp->tx_softq_head);
3257 	ASSERT(dp->tx_softq_tail == dp->tx_free_head);
3258 	if (flags & GEM_RESTART_KEEP_BUF) {
3259 		/* restore active tx buffers */
3260 		dp->tx_active_tail = dp->tx_active_head;
3261 		dp->tx_softq_head  = dp->tx_active_head;
3262 	} else {
3263 		gem_clean_tx_buf(dp);
3264 	}
3265 
3266 	return (ret);
3267 }
3268 
3269 static int
3270 gem_add_multicast(struct gem_dev *dp, const uint8_t *ep)
3271 {
3272 	int		cnt;
3273 	int		err;
3274 
3275 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3276 
3277 	mutex_enter(&dp->intrlock);
3278 	if (dp->mac_suspended) {
3279 		mutex_exit(&dp->intrlock);
3280 		return (GEM_FAILURE);
3281 	}
3282 
3283 	if (dp->mc_count_req++ < GEM_MAXMC) {
3284 		/* append the new address at the end of the mclist */
3285 		cnt = dp->mc_count;
3286 		bcopy(ep, dp->mc_list[cnt].addr.ether_addr_octet,
3287 		    ETHERADDRL);
3288 		if (dp->gc.gc_multicast_hash) {
3289 			dp->mc_list[cnt].hash =
3290 			    (*dp->gc.gc_multicast_hash)(dp, (uint8_t *)ep);
3291 		}
3292 		dp->mc_count = cnt + 1;
3293 	}
3294 
3295 	if (dp->mc_count_req != dp->mc_count) {
3296 		/* multicast address list overflow */
3297 		dp->rxmode |= RXMODE_MULTI_OVF;
3298 	} else {
3299 		dp->rxmode &= ~RXMODE_MULTI_OVF;
3300 	}
3301 
3302 	/* tell new multicast list to the hardware */
3303 	err = gem_mac_set_rx_filter(dp);
3304 
3305 	mutex_exit(&dp->intrlock);
3306 
3307 	return (err);
3308 }
3309 
3310 static int
3311 gem_remove_multicast(struct gem_dev *dp, const uint8_t *ep)
3312 {
3313 	size_t		len;
3314 	int		i;
3315 	int		cnt;
3316 	int		err;
3317 
3318 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3319 
3320 	mutex_enter(&dp->intrlock);
3321 	if (dp->mac_suspended) {
3322 		mutex_exit(&dp->intrlock);
3323 		return (GEM_FAILURE);
3324 	}
3325 
3326 	dp->mc_count_req--;
3327 	cnt = dp->mc_count;
3328 	for (i = 0; i < cnt; i++) {
3329 		if (bcmp(ep, &dp->mc_list[i].addr, ETHERADDRL)) {
3330 			continue;
3331 		}
3332 		/* shrink the mclist by copying forward */
3333 		len = (cnt - (i + 1)) * sizeof (*dp->mc_list);
3334 		if (len > 0) {
3335 			bcopy(&dp->mc_list[i+1], &dp->mc_list[i], len);
3336 		}
3337 		dp->mc_count--;
3338 		break;
3339 	}
3340 
3341 	if (dp->mc_count_req != dp->mc_count) {
3342 		/* multicast address list overflow */
3343 		dp->rxmode |= RXMODE_MULTI_OVF;
3344 	} else {
3345 		dp->rxmode &= ~RXMODE_MULTI_OVF;
3346 	}
3347 	/* In gem v2, don't hold xmitlock on calling set_rx_filter */
3348 	err = gem_mac_set_rx_filter(dp);
3349 
3350 	mutex_exit(&dp->intrlock);
3351 
3352 	return (err);
3353 }
3354 
3355 /* ============================================================== */
3356 /*
3357  * ND interface
3358  */
3359 /* ============================================================== */
3360 enum {
3361 	PARAM_AUTONEG_CAP,
3362 	PARAM_PAUSE_CAP,
3363 	PARAM_ASYM_PAUSE_CAP,
3364 	PARAM_1000FDX_CAP,
3365 	PARAM_1000HDX_CAP,
3366 	PARAM_100T4_CAP,
3367 	PARAM_100FDX_CAP,
3368 	PARAM_100HDX_CAP,
3369 	PARAM_10FDX_CAP,
3370 	PARAM_10HDX_CAP,
3371 
3372 	PARAM_ADV_AUTONEG_CAP,
3373 	PARAM_ADV_PAUSE_CAP,
3374 	PARAM_ADV_ASYM_PAUSE_CAP,
3375 	PARAM_ADV_1000FDX_CAP,
3376 	PARAM_ADV_1000HDX_CAP,
3377 	PARAM_ADV_100T4_CAP,
3378 	PARAM_ADV_100FDX_CAP,
3379 	PARAM_ADV_100HDX_CAP,
3380 	PARAM_ADV_10FDX_CAP,
3381 	PARAM_ADV_10HDX_CAP,
3382 
3383 	PARAM_LP_AUTONEG_CAP,
3384 	PARAM_LP_PAUSE_CAP,
3385 	PARAM_LP_ASYM_PAUSE_CAP,
3386 	PARAM_LP_1000FDX_CAP,
3387 	PARAM_LP_1000HDX_CAP,
3388 	PARAM_LP_100T4_CAP,
3389 	PARAM_LP_100FDX_CAP,
3390 	PARAM_LP_100HDX_CAP,
3391 	PARAM_LP_10FDX_CAP,
3392 	PARAM_LP_10HDX_CAP,
3393 
3394 	PARAM_LINK_STATUS,
3395 	PARAM_LINK_SPEED,
3396 	PARAM_LINK_DUPLEX,
3397 
3398 	PARAM_LINK_AUTONEG,
3399 	PARAM_LINK_RX_PAUSE,
3400 	PARAM_LINK_TX_PAUSE,
3401 
3402 	PARAM_LOOP_MODE,
3403 	PARAM_MSI_CNT,
3404 
3405 #ifdef DEBUG_RESUME
3406 	PARAM_RESUME_TEST,
3407 #endif
3408 	PARAM_COUNT
3409 };
3410 
3411 enum ioc_reply {
3412 	IOC_INVAL = -1,				/* bad, NAK with EINVAL	*/
3413 	IOC_DONE,				/* OK, reply sent	*/
3414 	IOC_ACK,				/* OK, just send ACK	*/
3415 	IOC_REPLY,				/* OK, just send reply	*/
3416 	IOC_RESTART_ACK,			/* OK, restart & ACK	*/
3417 	IOC_RESTART_REPLY			/* OK, restart & reply	*/
3418 };
3419 
3420 struct gem_nd_arg {
3421 	struct gem_dev	*dp;
3422 	int		item;
3423 };
3424 
3425 static int
3426 gem_param_get(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
3427 {
3428 	struct gem_dev	*dp = ((struct gem_nd_arg *)(void *)arg)->dp;
3429 	int		item = ((struct gem_nd_arg *)(void *)arg)->item;
3430 	long		val;
3431 
3432 	DPRINTF(0, (CE_CONT, "!%s: %s: called, item:%d",
3433 	    dp->name, __func__, item));
3434 
3435 	switch (item) {
3436 	case PARAM_AUTONEG_CAP:
3437 		val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
3438 		DPRINTF(0, (CE_CONT, "autoneg_cap:%d", val));
3439 		break;
3440 
3441 	case PARAM_PAUSE_CAP:
3442 		val = BOOLEAN(dp->gc.gc_flow_control & 1);
3443 		break;
3444 
3445 	case PARAM_ASYM_PAUSE_CAP:
3446 		val = BOOLEAN(dp->gc.gc_flow_control & 2);
3447 		break;
3448 
3449 	case PARAM_1000FDX_CAP:
3450 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
3451 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
3452 		break;
3453 
3454 	case PARAM_1000HDX_CAP:
3455 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
3456 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
3457 		break;
3458 
3459 	case PARAM_100T4_CAP:
3460 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
3461 		break;
3462 
3463 	case PARAM_100FDX_CAP:
3464 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
3465 		break;
3466 
3467 	case PARAM_100HDX_CAP:
3468 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
3469 		break;
3470 
3471 	case PARAM_10FDX_CAP:
3472 		val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
3473 		break;
3474 
3475 	case PARAM_10HDX_CAP:
3476 		val = BOOLEAN(dp->mii_status & MII_STATUS_10);
3477 		break;
3478 
3479 	case PARAM_ADV_AUTONEG_CAP:
3480 		val = dp->anadv_autoneg;
3481 		break;
3482 
3483 	case PARAM_ADV_PAUSE_CAP:
3484 		val = BOOLEAN(dp->anadv_flow_control & 1);
3485 		break;
3486 
3487 	case PARAM_ADV_ASYM_PAUSE_CAP:
3488 		val = BOOLEAN(dp->anadv_flow_control & 2);
3489 		break;
3490 
3491 	case PARAM_ADV_1000FDX_CAP:
3492 		val = dp->anadv_1000fdx;
3493 		break;
3494 
3495 	case PARAM_ADV_1000HDX_CAP:
3496 		val = dp->anadv_1000hdx;
3497 		break;
3498 
3499 	case PARAM_ADV_100T4_CAP:
3500 		val = dp->anadv_100t4;
3501 		break;
3502 
3503 	case PARAM_ADV_100FDX_CAP:
3504 		val = dp->anadv_100fdx;
3505 		break;
3506 
3507 	case PARAM_ADV_100HDX_CAP:
3508 		val = dp->anadv_100hdx;
3509 		break;
3510 
3511 	case PARAM_ADV_10FDX_CAP:
3512 		val = dp->anadv_10fdx;
3513 		break;
3514 
3515 	case PARAM_ADV_10HDX_CAP:
3516 		val = dp->anadv_10hdx;
3517 		break;
3518 
3519 	case PARAM_LP_AUTONEG_CAP:
3520 		val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3521 		break;
3522 
3523 	case PARAM_LP_PAUSE_CAP:
3524 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE);
3525 		break;
3526 
3527 	case PARAM_LP_ASYM_PAUSE_CAP:
3528 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASMPAUSE);
3529 		break;
3530 
3531 	case PARAM_LP_1000FDX_CAP:
3532 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
3533 		break;
3534 
3535 	case PARAM_LP_1000HDX_CAP:
3536 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
3537 		break;
3538 
3539 	case PARAM_LP_100T4_CAP:
3540 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4);
3541 		break;
3542 
3543 	case PARAM_LP_100FDX_CAP:
3544 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
3545 		break;
3546 
3547 	case PARAM_LP_100HDX_CAP:
3548 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
3549 		break;
3550 
3551 	case PARAM_LP_10FDX_CAP:
3552 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
3553 		break;
3554 
3555 	case PARAM_LP_10HDX_CAP:
3556 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
3557 		break;
3558 
3559 	case PARAM_LINK_STATUS:
3560 		val = (dp->mii_state == MII_STATE_LINKUP);
3561 		break;
3562 
3563 	case PARAM_LINK_SPEED:
3564 		val = gem_speed_value[dp->speed];
3565 		break;
3566 
3567 	case PARAM_LINK_DUPLEX:
3568 		val = 0;
3569 		if (dp->mii_state == MII_STATE_LINKUP) {
3570 			val = dp->full_duplex ? 2 : 1;
3571 		}
3572 		break;
3573 
3574 	case PARAM_LINK_AUTONEG:
3575 		val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3576 		break;
3577 
3578 	case PARAM_LINK_RX_PAUSE:
3579 		val = (dp->flow_control == FLOW_CONTROL_SYMMETRIC) ||
3580 		    (dp->flow_control == FLOW_CONTROL_RX_PAUSE);
3581 		break;
3582 
3583 	case PARAM_LINK_TX_PAUSE:
3584 		val = (dp->flow_control == FLOW_CONTROL_SYMMETRIC) ||
3585 		    (dp->flow_control == FLOW_CONTROL_TX_PAUSE);
3586 		break;
3587 
3588 #ifdef DEBUG_RESUME
3589 	case PARAM_RESUME_TEST:
3590 		val = 0;
3591 		break;
3592 #endif
3593 	default:
3594 		cmn_err(CE_WARN, "%s: unimplemented ndd control (%d)",
3595 		    dp->name, item);
3596 		break;
3597 	}
3598 
3599 	(void) mi_mpprintf(mp, "%ld", val);
3600 
3601 	return (0);
3602 }
3603 
3604 static int
3605 gem_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t arg, cred_t *credp)
3606 {
3607 	struct gem_dev	*dp = ((struct gem_nd_arg *)(void *)arg)->dp;
3608 	int		item = ((struct gem_nd_arg *)(void *)arg)->item;
3609 	long		val;
3610 	char		*end;
3611 
3612 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3613 	if (ddi_strtol(value, &end, 10, &val)) {
3614 		return (EINVAL);
3615 	}
3616 	if (end == value) {
3617 		return (EINVAL);
3618 	}
3619 
3620 	switch (item) {
3621 	case PARAM_ADV_AUTONEG_CAP:
3622 		if (val != 0 && val != 1) {
3623 			goto err;
3624 		}
3625 		if (val && (dp->mii_status & MII_STATUS_CANAUTONEG) == 0) {
3626 			goto err;
3627 		}
3628 		dp->anadv_autoneg = (int)val;
3629 		break;
3630 
3631 	case PARAM_ADV_PAUSE_CAP:
3632 		if (val != 0 && val != 1) {
3633 			goto err;
3634 		}
3635 		if (val) {
3636 			dp->anadv_flow_control |= 1;
3637 		} else {
3638 			dp->anadv_flow_control &= ~1;
3639 		}
3640 		break;
3641 
3642 	case PARAM_ADV_ASYM_PAUSE_CAP:
3643 		if (val != 0 && val != 1) {
3644 			goto err;
3645 		}
3646 		if (val) {
3647 			dp->anadv_flow_control |= 2;
3648 		} else {
3649 			dp->anadv_flow_control &= ~2;
3650 		}
3651 		break;
3652 
3653 	case PARAM_ADV_1000FDX_CAP:
3654 		if (val != 0 && val != 1) {
3655 			goto err;
3656 		}
3657 		if (val && (dp->mii_xstatus &
3658 		    (MII_XSTATUS_1000BASET_FD |
3659 		    MII_XSTATUS_1000BASEX_FD)) == 0) {
3660 			goto err;
3661 		}
3662 		dp->anadv_1000fdx = (int)val;
3663 		break;
3664 
3665 	case PARAM_ADV_1000HDX_CAP:
3666 		if (val != 0 && val != 1) {
3667 			goto err;
3668 		}
3669 		if (val && (dp->mii_xstatus &
3670 		    (MII_XSTATUS_1000BASET | MII_XSTATUS_1000BASEX)) == 0) {
3671 			goto err;
3672 		}
3673 		dp->anadv_1000hdx = (int)val;
3674 		break;
3675 
3676 	case PARAM_ADV_100T4_CAP:
3677 		if (val != 0 && val != 1) {
3678 			goto err;
3679 		}
3680 		if (val && (dp->mii_status & MII_STATUS_100_BASE_T4) == 0) {
3681 			goto err;
3682 		}
3683 		dp->anadv_100t4 = (int)val;
3684 		break;
3685 
3686 	case PARAM_ADV_100FDX_CAP:
3687 		if (val != 0 && val != 1) {
3688 			goto err;
3689 		}
3690 		if (val && (dp->mii_status & MII_STATUS_100_BASEX_FD) == 0) {
3691 			goto err;
3692 		}
3693 		dp->anadv_100fdx = (int)val;
3694 		break;
3695 
3696 	case PARAM_ADV_100HDX_CAP:
3697 		if (val != 0 && val != 1) {
3698 			goto err;
3699 		}
3700 		if (val && (dp->mii_status & MII_STATUS_100_BASEX) == 0) {
3701 			goto err;
3702 		}
3703 		dp->anadv_100hdx = (int)val;
3704 		break;
3705 
3706 	case PARAM_ADV_10FDX_CAP:
3707 		if (val != 0 && val != 1) {
3708 			goto err;
3709 		}
3710 		if (val && (dp->mii_status & MII_STATUS_10_FD) == 0) {
3711 			goto err;
3712 		}
3713 		dp->anadv_10fdx = (int)val;
3714 		break;
3715 
3716 	case PARAM_ADV_10HDX_CAP:
3717 		if (val != 0 && val != 1) {
3718 			goto err;
3719 		}
3720 		if (val && (dp->mii_status & MII_STATUS_10) == 0) {
3721 			goto err;
3722 		}
3723 		dp->anadv_10hdx = (int)val;
3724 		break;
3725 	}
3726 
3727 	/* sync with PHY */
3728 	gem_choose_forcedmode(dp);
3729 
3730 	dp->mii_state = MII_STATE_UNKNOWN;
3731 	if (dp->gc.gc_mii_hw_link_detection && dp->link_watcher_id == 0) {
3732 		/* XXX - Can we ignore the return code ? */
3733 		(void) gem_mii_link_check(dp);
3734 	}
3735 
3736 	return (0);
3737 err:
3738 	return (EINVAL);
3739 }
3740 
3741 static void
3742 gem_nd_load(struct gem_dev *dp, char *name, ndgetf_t gf, ndsetf_t sf, int item)
3743 {
3744 	struct gem_nd_arg	*arg;
3745 
3746 	ASSERT(item >= 0);
3747 	ASSERT(item < PARAM_COUNT);
3748 
3749 	arg = &((struct gem_nd_arg *)(void *)dp->nd_arg_p)[item];
3750 	arg->dp = dp;
3751 	arg->item = item;
3752 
3753 	DPRINTF(2, (CE_CONT, "!%s: %s: name:%s, item:%d",
3754 	    dp->name, __func__, name, item));
3755 	(void) nd_load(&dp->nd_data_p, name, gf, sf, (caddr_t)arg);
3756 }
3757 
3758 static void
3759 gem_nd_setup(struct gem_dev *dp)
3760 {
3761 	DPRINTF(0, (CE_CONT, "!%s: %s: called, mii_status:0x%b",
3762 	    dp->name, __func__, dp->mii_status, MII_STATUS_BITS));
3763 
3764 	ASSERT(dp->nd_arg_p == NULL);
3765 
3766 	dp->nd_arg_p =
3767 	    kmem_zalloc(sizeof (struct gem_nd_arg) * PARAM_COUNT, KM_SLEEP);
3768 
3769 #define	SETFUNC(x)	((x) ? gem_param_set : NULL)
3770 
3771 	gem_nd_load(dp, "autoneg_cap",
3772 	    gem_param_get, NULL, PARAM_AUTONEG_CAP);
3773 	gem_nd_load(dp, "pause_cap",
3774 	    gem_param_get, NULL, PARAM_PAUSE_CAP);
3775 	gem_nd_load(dp, "asym_pause_cap",
3776 	    gem_param_get, NULL, PARAM_ASYM_PAUSE_CAP);
3777 	gem_nd_load(dp, "1000fdx_cap",
3778 	    gem_param_get, NULL, PARAM_1000FDX_CAP);
3779 	gem_nd_load(dp, "1000hdx_cap",
3780 	    gem_param_get, NULL, PARAM_1000HDX_CAP);
3781 	gem_nd_load(dp, "100T4_cap",
3782 	    gem_param_get, NULL, PARAM_100T4_CAP);
3783 	gem_nd_load(dp, "100fdx_cap",
3784 	    gem_param_get, NULL, PARAM_100FDX_CAP);
3785 	gem_nd_load(dp, "100hdx_cap",
3786 	    gem_param_get, NULL, PARAM_100HDX_CAP);
3787 	gem_nd_load(dp, "10fdx_cap",
3788 	    gem_param_get, NULL, PARAM_10FDX_CAP);
3789 	gem_nd_load(dp, "10hdx_cap",
3790 	    gem_param_get, NULL, PARAM_10HDX_CAP);
3791 
3792 	/* Our advertised capabilities */
3793 	gem_nd_load(dp, "adv_autoneg_cap", gem_param_get,
3794 	    SETFUNC(dp->mii_status & MII_STATUS_CANAUTONEG),
3795 	    PARAM_ADV_AUTONEG_CAP);
3796 	gem_nd_load(dp, "adv_pause_cap", gem_param_get,
3797 	    SETFUNC(dp->gc.gc_flow_control & 1),
3798 	    PARAM_ADV_PAUSE_CAP);
3799 	gem_nd_load(dp, "adv_asym_pause_cap", gem_param_get,
3800 	    SETFUNC(dp->gc.gc_flow_control & 2),
3801 	    PARAM_ADV_ASYM_PAUSE_CAP);
3802 	gem_nd_load(dp, "adv_1000fdx_cap", gem_param_get,
3803 	    SETFUNC(dp->mii_xstatus &
3804 	    (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD)),
3805 	    PARAM_ADV_1000FDX_CAP);
3806 	gem_nd_load(dp, "adv_1000hdx_cap", gem_param_get,
3807 	    SETFUNC(dp->mii_xstatus &
3808 	    (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET)),
3809 	    PARAM_ADV_1000HDX_CAP);
3810 	gem_nd_load(dp, "adv_100T4_cap", gem_param_get,
3811 	    SETFUNC((dp->mii_status & MII_STATUS_100_BASE_T4) &&
3812 	    !dp->mii_advert_ro),
3813 	    PARAM_ADV_100T4_CAP);
3814 	gem_nd_load(dp, "adv_100fdx_cap", gem_param_get,
3815 	    SETFUNC((dp->mii_status & MII_STATUS_100_BASEX_FD) &&
3816 	    !dp->mii_advert_ro),
3817 	    PARAM_ADV_100FDX_CAP);
3818 	gem_nd_load(dp, "adv_100hdx_cap", gem_param_get,
3819 	    SETFUNC((dp->mii_status & MII_STATUS_100_BASEX) &&
3820 	    !dp->mii_advert_ro),
3821 	    PARAM_ADV_100HDX_CAP);
3822 	gem_nd_load(dp, "adv_10fdx_cap", gem_param_get,
3823 	    SETFUNC((dp->mii_status & MII_STATUS_10_FD) &&
3824 	    !dp->mii_advert_ro),
3825 	    PARAM_ADV_10FDX_CAP);
3826 	gem_nd_load(dp, "adv_10hdx_cap", gem_param_get,
3827 	    SETFUNC((dp->mii_status & MII_STATUS_10) &&
3828 	    !dp->mii_advert_ro),
3829 	    PARAM_ADV_10HDX_CAP);
3830 
3831 	/* Partner's advertised capabilities */
3832 	gem_nd_load(dp, "lp_autoneg_cap",
3833 	    gem_param_get, NULL, PARAM_LP_AUTONEG_CAP);
3834 	gem_nd_load(dp, "lp_pause_cap",
3835 	    gem_param_get, NULL, PARAM_LP_PAUSE_CAP);
3836 	gem_nd_load(dp, "lp_asym_pause_cap",
3837 	    gem_param_get, NULL, PARAM_LP_ASYM_PAUSE_CAP);
3838 	gem_nd_load(dp, "lp_1000fdx_cap",
3839 	    gem_param_get, NULL, PARAM_LP_1000FDX_CAP);
3840 	gem_nd_load(dp, "lp_1000hdx_cap",
3841 	    gem_param_get, NULL, PARAM_LP_1000HDX_CAP);
3842 	gem_nd_load(dp, "lp_100T4_cap",
3843 	    gem_param_get, NULL, PARAM_LP_100T4_CAP);
3844 	gem_nd_load(dp, "lp_100fdx_cap",
3845 	    gem_param_get, NULL, PARAM_LP_100FDX_CAP);
3846 	gem_nd_load(dp, "lp_100hdx_cap",
3847 	    gem_param_get, NULL, PARAM_LP_100HDX_CAP);
3848 	gem_nd_load(dp, "lp_10fdx_cap",
3849 	    gem_param_get, NULL, PARAM_LP_10FDX_CAP);
3850 	gem_nd_load(dp, "lp_10hdx_cap",
3851 	    gem_param_get, NULL, PARAM_LP_10HDX_CAP);
3852 
3853 	/* Current operating modes */
3854 	gem_nd_load(dp, "link_status",
3855 	    gem_param_get, NULL, PARAM_LINK_STATUS);
3856 	gem_nd_load(dp, "link_speed",
3857 	    gem_param_get, NULL, PARAM_LINK_SPEED);
3858 	gem_nd_load(dp, "link_duplex",
3859 	    gem_param_get, NULL, PARAM_LINK_DUPLEX);
3860 	gem_nd_load(dp, "link_autoneg",
3861 	    gem_param_get, NULL, PARAM_LINK_AUTONEG);
3862 	gem_nd_load(dp, "link_rx_pause",
3863 	    gem_param_get, NULL, PARAM_LINK_RX_PAUSE);
3864 	gem_nd_load(dp, "link_tx_pause",
3865 	    gem_param_get, NULL, PARAM_LINK_TX_PAUSE);
3866 #ifdef DEBUG_RESUME
3867 	gem_nd_load(dp, "resume_test",
3868 	    gem_param_get, NULL, PARAM_RESUME_TEST);
3869 #endif
3870 #undef	SETFUNC
3871 }
3872 
3873 static
3874 enum ioc_reply
3875 gem_nd_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
3876 {
3877 	boolean_t	ok;
3878 
3879 	ASSERT(mutex_owned(&dp->intrlock));
3880 
3881 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3882 
3883 	switch (iocp->ioc_cmd) {
3884 	case ND_GET:
3885 		ok = nd_getset(wq, dp->nd_data_p, mp);
3886 		DPRINTF(0, (CE_CONT,
3887 		    "%s: get %s", dp->name, ok ? "OK" : "FAIL"));
3888 		return (ok ? IOC_REPLY : IOC_INVAL);
3889 
3890 	case ND_SET:
3891 		ok = nd_getset(wq, dp->nd_data_p, mp);
3892 
3893 		DPRINTF(0, (CE_CONT, "%s: set %s err %d",
3894 		    dp->name, ok ? "OK" : "FAIL", iocp->ioc_error));
3895 
3896 		if (!ok) {
3897 			return (IOC_INVAL);
3898 		}
3899 
3900 		if (iocp->ioc_error) {
3901 			return (IOC_REPLY);
3902 		}
3903 
3904 		return (IOC_RESTART_REPLY);
3905 	}
3906 
3907 	cmn_err(CE_WARN, "%s: invalid cmd 0x%x", dp->name, iocp->ioc_cmd);
3908 
3909 	return (IOC_INVAL);
3910 }
3911 
3912 static void
3913 gem_nd_cleanup(struct gem_dev *dp)
3914 {
3915 	ASSERT(dp->nd_data_p != NULL);
3916 	ASSERT(dp->nd_arg_p != NULL);
3917 
3918 	nd_free(&dp->nd_data_p);
3919 
3920 	kmem_free(dp->nd_arg_p, sizeof (struct gem_nd_arg) * PARAM_COUNT);
3921 	dp->nd_arg_p = NULL;
3922 }
3923 
3924 static void
3925 gem_mac_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp)
3926 {
3927 	struct iocblk	*iocp;
3928 	enum ioc_reply	status;
3929 	int		cmd;
3930 
3931 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3932 
3933 	/*
3934 	 * Validate the command before bothering with the mutex ...
3935 	 */
3936 	iocp = (void *)mp->b_rptr;
3937 	iocp->ioc_error = 0;
3938 	cmd = iocp->ioc_cmd;
3939 
3940 	DPRINTF(0, (CE_CONT, "%s: %s cmd:0x%x", dp->name, __func__, cmd));
3941 
3942 	mutex_enter(&dp->intrlock);
3943 	mutex_enter(&dp->xmitlock);
3944 
3945 	switch (cmd) {
3946 	default:
3947 		_NOTE(NOTREACHED)
3948 		status = IOC_INVAL;
3949 		break;
3950 
3951 	case ND_GET:
3952 	case ND_SET:
3953 		status = gem_nd_ioctl(dp, wq, mp, iocp);
3954 		break;
3955 	}
3956 
3957 	mutex_exit(&dp->xmitlock);
3958 	mutex_exit(&dp->intrlock);
3959 
3960 #ifdef DEBUG_RESUME
3961 	if (cmd == ND_GET)  {
3962 		gem_suspend(dp->dip);
3963 		gem_resume(dp->dip);
3964 	}
3965 #endif
3966 	/*
3967 	 * Finally, decide how to reply
3968 	 */
3969 	switch (status) {
3970 	default:
3971 	case IOC_INVAL:
3972 		/*
3973 		 * Error, reply with a NAK and EINVAL or the specified error
3974 		 */
3975 		miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
3976 		    EINVAL : iocp->ioc_error);
3977 		break;
3978 
3979 	case IOC_DONE:
3980 		/*
3981 		 * OK, reply already sent
3982 		 */
3983 		break;
3984 
3985 	case IOC_RESTART_ACK:
3986 	case IOC_ACK:
3987 		/*
3988 		 * OK, reply with an ACK
3989 		 */
3990 		miocack(wq, mp, 0, 0);
3991 		break;
3992 
3993 	case IOC_RESTART_REPLY:
3994 	case IOC_REPLY:
3995 		/*
3996 		 * OK, send prepared reply as ACK or NAK
3997 		 */
3998 		mp->b_datap->db_type =
3999 		    iocp->ioc_error == 0 ? M_IOCACK : M_IOCNAK;
4000 		qreply(wq, mp);
4001 		break;
4002 	}
4003 }
4004 
4005 #ifndef SYS_MAC_H
4006 #define	XCVR_UNDEFINED	0
4007 #define	XCVR_NONE	1
4008 #define	XCVR_10		2
4009 #define	XCVR_100T4	3
4010 #define	XCVR_100X	4
4011 #define	XCVR_100T2	5
4012 #define	XCVR_1000X	6
4013 #define	XCVR_1000T	7
4014 #endif
4015 static int
4016 gem_mac_xcvr_inuse(struct gem_dev *dp)
4017 {
4018 	int	val = XCVR_UNDEFINED;
4019 
4020 	if ((dp->mii_status & MII_STATUS_XSTATUS) == 0) {
4021 		if (dp->mii_status & MII_STATUS_100_BASE_T4) {
4022 			val = XCVR_100T4;
4023 		} else if (dp->mii_status &
4024 		    (MII_STATUS_100_BASEX_FD |
4025 		    MII_STATUS_100_BASEX)) {
4026 			val = XCVR_100X;
4027 		} else if (dp->mii_status &
4028 		    (MII_STATUS_100_BASE_T2_FD |
4029 		    MII_STATUS_100_BASE_T2)) {
4030 			val = XCVR_100T2;
4031 		} else if (dp->mii_status &
4032 		    (MII_STATUS_10_FD | MII_STATUS_10)) {
4033 			val = XCVR_10;
4034 		}
4035 	} else if (dp->mii_xstatus &
4036 	    (MII_XSTATUS_1000BASET_FD | MII_XSTATUS_1000BASET)) {
4037 		val = XCVR_1000T;
4038 	} else if (dp->mii_xstatus &
4039 	    (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASEX)) {
4040 		val = XCVR_1000X;
4041 	}
4042 
4043 	return (val);
4044 }
4045 
4046 /* ============================================================== */
4047 /*
4048  * GLDv3 interface
4049  */
4050 /* ============================================================== */
4051 static int		gem_m_getstat(void *, uint_t, uint64_t *);
4052 static int		gem_m_start(void *);
4053 static void		gem_m_stop(void *);
4054 static int		gem_m_setpromisc(void *, boolean_t);
4055 static int		gem_m_multicst(void *, boolean_t, const uint8_t *);
4056 static int		gem_m_unicst(void *, const uint8_t *);
4057 static mblk_t		*gem_m_tx(void *, mblk_t *);
4058 static void		gem_m_ioctl(void *, queue_t *, mblk_t *);
4059 static boolean_t	gem_m_getcapab(void *, mac_capab_t, void *);
4060 
4061 #define	GEM_M_CALLBACK_FLAGS	(MC_IOCTL | MC_GETCAPAB)
4062 
4063 static mac_callbacks_t gem_m_callbacks = {
4064 	GEM_M_CALLBACK_FLAGS,
4065 	gem_m_getstat,
4066 	gem_m_start,
4067 	gem_m_stop,
4068 	gem_m_setpromisc,
4069 	gem_m_multicst,
4070 	gem_m_unicst,
4071 	gem_m_tx,
4072 	NULL,
4073 	gem_m_ioctl,
4074 	gem_m_getcapab,
4075 };
4076 
4077 static int
4078 gem_m_start(void *arg)
4079 {
4080 	int		err = 0;
4081 	struct gem_dev *dp = arg;
4082 
4083 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4084 
4085 	mutex_enter(&dp->intrlock);
4086 	if (dp->mac_suspended) {
4087 		err = EIO;
4088 		goto x;
4089 	}
4090 	if (gem_mac_init(dp) != GEM_SUCCESS) {
4091 		err = EIO;
4092 		goto x;
4093 	}
4094 	dp->nic_state = NIC_STATE_INITIALIZED;
4095 
4096 	/* reset rx filter state */
4097 	dp->mc_count = 0;
4098 	dp->mc_count_req = 0;
4099 
4100 	/* setup media mode if the link have been up */
4101 	if (dp->mii_state == MII_STATE_LINKUP) {
4102 		(dp->gc.gc_set_media)(dp);
4103 	}
4104 
4105 	/* setup initial rx filter */
4106 	bcopy(dp->dev_addr.ether_addr_octet,
4107 	    dp->cur_addr.ether_addr_octet, ETHERADDRL);
4108 	dp->rxmode |= RXMODE_ENABLE;
4109 
4110 	if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4111 		err = EIO;
4112 		goto x;
4113 	}
4114 
4115 	dp->nic_state = NIC_STATE_ONLINE;
4116 	if (dp->mii_state == MII_STATE_LINKUP) {
4117 		if (gem_mac_start(dp) != GEM_SUCCESS) {
4118 			err = EIO;
4119 			goto x;
4120 		}
4121 	}
4122 
4123 	dp->timeout_id = timeout((void (*)(void *))gem_tx_timeout,
4124 	    (void *)dp, dp->gc.gc_tx_timeout_interval);
4125 	mutex_exit(&dp->intrlock);
4126 
4127 	return (0);
4128 x:
4129 	dp->nic_state = NIC_STATE_STOPPED;
4130 	mutex_exit(&dp->intrlock);
4131 	return (err);
4132 }
4133 
4134 static void
4135 gem_m_stop(void *arg)
4136 {
4137 	struct gem_dev	*dp = arg;
4138 
4139 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4140 
4141 	/* stop rx */
4142 	mutex_enter(&dp->intrlock);
4143 	if (dp->mac_suspended) {
4144 		mutex_exit(&dp->intrlock);
4145 		return;
4146 	}
4147 	dp->rxmode &= ~RXMODE_ENABLE;
4148 	(void) gem_mac_set_rx_filter(dp);
4149 	mutex_exit(&dp->intrlock);
4150 
4151 	/* stop tx timeout watcher */
4152 	if (dp->timeout_id) {
4153 		while (untimeout(dp->timeout_id) == -1)
4154 			;
4155 		dp->timeout_id = 0;
4156 	}
4157 
4158 	/* make the nic state inactive */
4159 	mutex_enter(&dp->intrlock);
4160 	if (dp->mac_suspended) {
4161 		mutex_exit(&dp->intrlock);
4162 		return;
4163 	}
4164 	dp->nic_state = NIC_STATE_STOPPED;
4165 
4166 	/* we need deassert mac_active due to block interrupt handler */
4167 	mutex_enter(&dp->xmitlock);
4168 	dp->mac_active = B_FALSE;
4169 	mutex_exit(&dp->xmitlock);
4170 
4171 	/* block interrupts */
4172 	while (dp->intr_busy) {
4173 		cv_wait(&dp->tx_drain_cv, &dp->intrlock);
4174 	}
4175 	(void) gem_mac_stop(dp, 0);
4176 	mutex_exit(&dp->intrlock);
4177 }
4178 
4179 static int
4180 gem_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
4181 {
4182 	int		err;
4183 	int		ret;
4184 	struct gem_dev	*dp = arg;
4185 
4186 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4187 
4188 	if (add) {
4189 		ret = gem_add_multicast(dp, ep);
4190 	} else {
4191 		ret = gem_remove_multicast(dp, ep);
4192 	}
4193 
4194 	err = 0;
4195 	if (ret != GEM_SUCCESS) {
4196 		err = EIO;
4197 	}
4198 
4199 	return (err);
4200 }
4201 
4202 static int
4203 gem_m_setpromisc(void *arg, boolean_t on)
4204 {
4205 	int		err = 0;	/* no error */
4206 	struct gem_dev	*dp = arg;
4207 
4208 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4209 
4210 	mutex_enter(&dp->intrlock);
4211 	if (dp->mac_suspended) {
4212 		mutex_exit(&dp->intrlock);
4213 		return (EIO);
4214 	}
4215 	if (on) {
4216 		dp->rxmode |= RXMODE_PROMISC;
4217 	} else {
4218 		dp->rxmode &= ~RXMODE_PROMISC;
4219 	}
4220 
4221 	if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4222 		err = EIO;
4223 	}
4224 	mutex_exit(&dp->intrlock);
4225 
4226 	return (err);
4227 }
4228 
4229 int
4230 gem_m_getstat(void *arg, uint_t stat, uint64_t *valp)
4231 {
4232 	struct gem_dev		*dp = arg;
4233 	struct gem_stats	*gstp = &dp->stats;
4234 	uint64_t		val = 0;
4235 
4236 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4237 
4238 	if (mutex_owned(&dp->intrlock)) {
4239 		if (dp->mac_suspended) {
4240 			return (EIO);
4241 		}
4242 	} else {
4243 		mutex_enter(&dp->intrlock);
4244 		if (dp->mac_suspended) {
4245 			mutex_exit(&dp->intrlock);
4246 			return (EIO);
4247 		}
4248 		mutex_exit(&dp->intrlock);
4249 	}
4250 
4251 	if ((*dp->gc.gc_get_stats)(dp) != GEM_SUCCESS) {
4252 		return (EIO);
4253 	}
4254 
4255 	switch (stat) {
4256 	case MAC_STAT_IFSPEED:
4257 		val = gem_speed_value[dp->speed] *1000000ull;
4258 		break;
4259 
4260 	case MAC_STAT_MULTIRCV:
4261 		val = gstp->rmcast;
4262 		break;
4263 
4264 	case MAC_STAT_BRDCSTRCV:
4265 		val = gstp->rbcast;
4266 		break;
4267 
4268 	case MAC_STAT_MULTIXMT:
4269 		val = gstp->omcast;
4270 		break;
4271 
4272 	case MAC_STAT_BRDCSTXMT:
4273 		val = gstp->obcast;
4274 		break;
4275 
4276 	case MAC_STAT_NORCVBUF:
4277 		val = gstp->norcvbuf + gstp->missed;
4278 		break;
4279 
4280 	case MAC_STAT_IERRORS:
4281 		val = gstp->errrcv;
4282 		break;
4283 
4284 	case MAC_STAT_NOXMTBUF:
4285 		val = gstp->noxmtbuf;
4286 		break;
4287 
4288 	case MAC_STAT_OERRORS:
4289 		val = gstp->errxmt;
4290 		break;
4291 
4292 	case MAC_STAT_COLLISIONS:
4293 		val = gstp->collisions;
4294 		break;
4295 
4296 	case MAC_STAT_RBYTES:
4297 		val = gstp->rbytes;
4298 		break;
4299 
4300 	case MAC_STAT_IPACKETS:
4301 		val = gstp->rpackets;
4302 		break;
4303 
4304 	case MAC_STAT_OBYTES:
4305 		val = gstp->obytes;
4306 		break;
4307 
4308 	case MAC_STAT_OPACKETS:
4309 		val = gstp->opackets;
4310 		break;
4311 
4312 	case MAC_STAT_UNDERFLOWS:
4313 		val = gstp->underflow;
4314 		break;
4315 
4316 	case MAC_STAT_OVERFLOWS:
4317 		val = gstp->overflow;
4318 		break;
4319 
4320 	case ETHER_STAT_ALIGN_ERRORS:
4321 		val = gstp->frame;
4322 		break;
4323 
4324 	case ETHER_STAT_FCS_ERRORS:
4325 		val = gstp->crc;
4326 		break;
4327 
4328 	case ETHER_STAT_FIRST_COLLISIONS:
4329 		val = gstp->first_coll;
4330 		break;
4331 
4332 	case ETHER_STAT_MULTI_COLLISIONS:
4333 		val = gstp->multi_coll;
4334 		break;
4335 
4336 	case ETHER_STAT_SQE_ERRORS:
4337 		val = gstp->sqe;
4338 		break;
4339 
4340 	case ETHER_STAT_DEFER_XMTS:
4341 		val = gstp->defer;
4342 		break;
4343 
4344 	case ETHER_STAT_TX_LATE_COLLISIONS:
4345 		val = gstp->xmtlatecoll;
4346 		break;
4347 
4348 	case ETHER_STAT_EX_COLLISIONS:
4349 		val = gstp->excoll;
4350 		break;
4351 
4352 	case ETHER_STAT_MACXMT_ERRORS:
4353 		val = gstp->xmit_internal_err;
4354 		break;
4355 
4356 	case ETHER_STAT_CARRIER_ERRORS:
4357 		val = gstp->nocarrier;
4358 		break;
4359 
4360 	case ETHER_STAT_TOOLONG_ERRORS:
4361 		val = gstp->frame_too_long;
4362 		break;
4363 
4364 	case ETHER_STAT_MACRCV_ERRORS:
4365 		val = gstp->rcv_internal_err;
4366 		break;
4367 
4368 	case ETHER_STAT_XCVR_ADDR:
4369 		val = dp->mii_phy_addr;
4370 		break;
4371 
4372 	case ETHER_STAT_XCVR_ID:
4373 		val = dp->mii_phy_id;
4374 		break;
4375 
4376 	case ETHER_STAT_XCVR_INUSE:
4377 		val = gem_mac_xcvr_inuse(dp);
4378 		break;
4379 
4380 	case ETHER_STAT_CAP_1000FDX:
4381 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
4382 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
4383 		break;
4384 
4385 	case ETHER_STAT_CAP_1000HDX:
4386 		val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
4387 		    (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
4388 		break;
4389 
4390 	case ETHER_STAT_CAP_100FDX:
4391 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4392 		break;
4393 
4394 	case ETHER_STAT_CAP_100HDX:
4395 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4396 		break;
4397 
4398 	case ETHER_STAT_CAP_10FDX:
4399 		val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4400 		break;
4401 
4402 	case ETHER_STAT_CAP_10HDX:
4403 		val = BOOLEAN(dp->mii_status & MII_STATUS_10);
4404 		break;
4405 
4406 	case ETHER_STAT_CAP_ASMPAUSE:
4407 		val = BOOLEAN(dp->gc.gc_flow_control & 2);
4408 		break;
4409 
4410 	case ETHER_STAT_CAP_PAUSE:
4411 		val = BOOLEAN(dp->gc.gc_flow_control & 1);
4412 		break;
4413 
4414 	case ETHER_STAT_CAP_AUTONEG:
4415 		val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4416 		break;
4417 
4418 	case ETHER_STAT_ADV_CAP_1000FDX:
4419 		val = dp->anadv_1000fdx;
4420 		break;
4421 
4422 	case ETHER_STAT_ADV_CAP_1000HDX:
4423 		val = dp->anadv_1000hdx;
4424 		break;
4425 
4426 	case ETHER_STAT_ADV_CAP_100FDX:
4427 		val = dp->anadv_100fdx;
4428 		break;
4429 
4430 	case ETHER_STAT_ADV_CAP_100HDX:
4431 		val = dp->anadv_100hdx;
4432 		break;
4433 
4434 	case ETHER_STAT_ADV_CAP_10FDX:
4435 		val = dp->anadv_10fdx;
4436 		break;
4437 
4438 	case ETHER_STAT_ADV_CAP_10HDX:
4439 		val = dp->anadv_10hdx;
4440 		break;
4441 
4442 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
4443 		val = BOOLEAN(dp->anadv_flow_control & 2);
4444 		break;
4445 
4446 	case ETHER_STAT_ADV_CAP_PAUSE:
4447 		val = BOOLEAN(dp->anadv_flow_control & 1);
4448 		break;
4449 
4450 	case ETHER_STAT_ADV_CAP_AUTONEG:
4451 		val = dp->anadv_autoneg;
4452 		break;
4453 
4454 	case ETHER_STAT_LP_CAP_1000FDX:
4455 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
4456 		break;
4457 
4458 	case ETHER_STAT_LP_CAP_1000HDX:
4459 		val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
4460 		break;
4461 
4462 	case ETHER_STAT_LP_CAP_100FDX:
4463 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
4464 		break;
4465 
4466 	case ETHER_STAT_LP_CAP_100HDX:
4467 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
4468 		break;
4469 
4470 	case ETHER_STAT_LP_CAP_10FDX:
4471 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
4472 		break;
4473 
4474 	case ETHER_STAT_LP_CAP_10HDX:
4475 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
4476 		break;
4477 
4478 	case ETHER_STAT_LP_CAP_ASMPAUSE:
4479 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASMPAUSE);
4480 		break;
4481 
4482 	case ETHER_STAT_LP_CAP_PAUSE:
4483 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE);
4484 		break;
4485 
4486 	case ETHER_STAT_LP_CAP_AUTONEG:
4487 		val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
4488 		break;
4489 
4490 	case ETHER_STAT_LINK_ASMPAUSE:
4491 		val = BOOLEAN(dp->flow_control & 2);
4492 		break;
4493 
4494 	case ETHER_STAT_LINK_PAUSE:
4495 		val = BOOLEAN(dp->flow_control & 1);
4496 		break;
4497 
4498 	case ETHER_STAT_LINK_AUTONEG:
4499 		val = dp->anadv_autoneg &&
4500 		    BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
4501 		break;
4502 
4503 	case ETHER_STAT_LINK_DUPLEX:
4504 		val = (dp->mii_state == MII_STATE_LINKUP) ?
4505 		    (dp->full_duplex ? 2 : 1) : 0;
4506 		break;
4507 
4508 	case ETHER_STAT_TOOSHORT_ERRORS:
4509 		val = gstp->runt;
4510 		break;
4511 	case ETHER_STAT_LP_REMFAULT:
4512 		val = BOOLEAN(dp->mii_lpable & MII_AN_ADVERT_REMFAULT);
4513 		break;
4514 
4515 	case ETHER_STAT_JABBER_ERRORS:
4516 		val = gstp->jabber;
4517 		break;
4518 
4519 	case ETHER_STAT_CAP_100T4:
4520 		val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
4521 		break;
4522 
4523 	case ETHER_STAT_ADV_CAP_100T4:
4524 		val = dp->anadv_100t4;
4525 		break;
4526 
4527 	case ETHER_STAT_LP_CAP_100T4:
4528 		val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4);
4529 		break;
4530 
4531 	default:
4532 #if GEM_DEBUG_LEVEL > 2
4533 		cmn_err(CE_WARN,
4534 		    "%s: unrecognized parameter value = %d",
4535 		    __func__, stat);
4536 #endif
4537 		return (ENOTSUP);
4538 	}
4539 
4540 	*valp = val;
4541 
4542 	return (0);
4543 }
4544 
4545 static int
4546 gem_m_unicst(void *arg, const uint8_t *mac)
4547 {
4548 	int		err = 0;
4549 	struct gem_dev	*dp = arg;
4550 
4551 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4552 
4553 	mutex_enter(&dp->intrlock);
4554 	if (dp->mac_suspended) {
4555 		mutex_exit(&dp->intrlock);
4556 		return (EIO);
4557 	}
4558 	bcopy(mac, dp->cur_addr.ether_addr_octet, ETHERADDRL);
4559 	dp->rxmode |= RXMODE_ENABLE;
4560 
4561 	if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4562 		err = EIO;
4563 	}
4564 	mutex_exit(&dp->intrlock);
4565 
4566 	return (err);
4567 }
4568 
4569 /*
4570  * gem_m_tx is used only for sending data packets into ethernet wire.
4571  */
4572 static mblk_t *
4573 gem_m_tx(void *arg, mblk_t *mp)
4574 {
4575 	uint32_t	flags = 0;
4576 	struct gem_dev	*dp = arg;
4577 	mblk_t		*tp;
4578 
4579 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4580 
4581 	ASSERT(dp->nic_state == NIC_STATE_ONLINE);
4582 	if (dp->mii_state != MII_STATE_LINKUP) {
4583 		/* Some nics hate to send packets when the link is down. */
4584 		while (mp) {
4585 			tp = mp->b_next;
4586 			mp->b_next = NULL;
4587 			freemsg(mp);
4588 			mp = tp;
4589 		}
4590 		return (NULL);
4591 	}
4592 
4593 	return (gem_send_common(dp, mp, flags));
4594 }
4595 
4596 static void
4597 gem_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
4598 {
4599 	DPRINTF(0, (CE_CONT, "!%s: %s: called",
4600 	    ((struct gem_dev *)arg)->name, __func__));
4601 
4602 	gem_mac_ioctl((struct gem_dev *)arg, wq, mp);
4603 }
4604 
4605 /* ARGSUSED */
4606 static boolean_t
4607 gem_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
4608 {
4609 	return (B_FALSE);
4610 }
4611 
4612 static void
4613 gem_gld3_init(struct gem_dev *dp, mac_register_t *macp)
4614 {
4615 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
4616 	macp->m_driver = dp;
4617 	macp->m_dip = dp->dip;
4618 	macp->m_src_addr = dp->dev_addr.ether_addr_octet;
4619 	macp->m_callbacks = &gem_m_callbacks;
4620 	macp->m_min_sdu = 0;
4621 	macp->m_max_sdu = dp->mtu;
4622 
4623 	if (dp->misc_flag & GEM_VLAN) {
4624 		macp->m_margin = VTAG_SIZE;
4625 	}
4626 }
4627 
4628 /* ======================================================================== */
4629 /*
4630  * attach/detatch support
4631  */
4632 /* ======================================================================== */
4633 static void
4634 gem_read_conf(struct gem_dev *dp)
4635 {
4636 	int	val;
4637 
4638 	DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4639 
4640 	/*
4641 	 * Get media mode infomation from .conf file
4642 	 */
4643 	dp->anadv_autoneg = gem_prop_get_int(dp, "adv_autoneg_cap", 1) != 0;
4644 	dp->anadv_1000fdx = gem_prop_get_int(dp, "adv_1000fdx_cap", 1) != 0;
4645 	dp->anadv_1000hdx = gem_prop_get_int(dp, "adv_1000hdx_cap", 1) != 0;
4646 	dp->anadv_100t4   = gem_prop_get_int(dp, "adv_100T4_cap", 1) != 0;
4647 	dp->anadv_100fdx  = gem_prop_get_int(dp, "adv_100fdx_cap", 1) != 0;
4648 	dp->anadv_100hdx  = gem_prop_get_int(dp, "adv_100hdx_cap", 1) != 0;
4649 	dp->anadv_10fdx   = gem_prop_get_int(dp, "adv_10fdx_cap", 1) != 0;
4650 	dp->anadv_10hdx   = gem_prop_get_int(dp, "adv_10hdx_cap", 1) != 0;
4651 
4652 	if ((ddi_prop_exists(DDI_DEV_T_ANY, dp->dip,
4653 	    DDI_PROP_DONTPASS, "full-duplex"))) {
4654 		dp->full_duplex = gem_prop_get_int(dp, "full-duplex", 1) != 0;
4655 		dp->anadv_autoneg = B_FALSE;
4656 		if (dp->full_duplex) {
4657 			dp->anadv_1000hdx = B_FALSE;
4658 			dp->anadv_100hdx = B_FALSE;
4659 			dp->anadv_10hdx = B_FALSE;
4660 		} else {
4661 			dp->anadv_1000fdx = B_FALSE;
4662 			dp->anadv_100fdx = B_FALSE;
4663 			dp->anadv_10fdx = B_FALSE;
4664 		}
4665 	}
4666 
4667 	if ((val = gem_prop_get_int(dp, "speed", 0)) > 0) {
4668 		dp->anadv_autoneg = B_FALSE;
4669 		switch (val) {
4670 		case 1000:
4671 			dp->speed = GEM_SPD_1000;
4672 			dp->anadv_100t4   = B_FALSE;
4673 			dp->anadv_100fdx  = B_FALSE;
4674 			dp->anadv_100hdx  = B_FALSE;
4675 			dp->anadv_10fdx   = B_FALSE;
4676 			dp->anadv_10hdx   = B_FALSE;
4677 			break;
4678 		case 100:
4679 			dp->speed = GEM_SPD_100;
4680 			dp->anadv_1000fdx = B_FALSE;
4681 			dp->anadv_1000hdx = B_FALSE;
4682 			dp->anadv_10fdx   = B_FALSE;
4683 			dp->anadv_10hdx   = B_FALSE;
4684 			break;
4685 		case 10:
4686 			dp->speed = GEM_SPD_10;
4687 			dp->anadv_1000fdx = B_FALSE;
4688 			dp->anadv_1000hdx = B_FALSE;
4689 			dp->anadv_100t4   = B_FALSE;
4690 			dp->anadv_100fdx  = B_FALSE;
4691 			dp->anadv_100hdx  = B_FALSE;
4692 			break;
4693 		default:
4694 			cmn_err(CE_WARN,
4695 			    "!%s: property %s: illegal value:%d",
4696 			    dp->name, "speed", val);
4697 			dp->anadv_autoneg = B_TRUE;
4698 			break;
4699 		}
4700 	}
4701 
4702 	val = gem_prop_get_int(dp, "flow-control", dp->gc.gc_flow_control);
4703 	if (val > FLOW_CONTROL_RX_PAUSE || val < FLOW_CONTROL_NONE) {
4704 		cmn_err(CE_WARN,
4705 		    "!%s: property %s: illegal value:%d",
4706 		    dp->name, "flow-control", val);
4707 	} else {
4708 		val = min(val, dp->gc.gc_flow_control);
4709 	}
4710 	dp->anadv_flow_control = val;
4711 
4712 	if (gem_prop_get_int(dp, "nointr", 0)) {
4713 		dp->misc_flag |= GEM_NOINTR;
4714 		cmn_err(CE_NOTE, "!%s: polling mode enabled", dp->name);
4715 	}
4716 
4717 	dp->mtu = gem_prop_get_int(dp, "mtu", dp->mtu);
4718 	dp->txthr = gem_prop_get_int(dp, "txthr", dp->txthr);
4719 	dp->rxthr = gem_prop_get_int(dp, "rxthr", dp->rxthr);
4720 	dp->txmaxdma = gem_prop_get_int(dp, "txmaxdma", dp->txmaxdma);
4721 	dp->rxmaxdma = gem_prop_get_int(dp, "rxmaxdma", dp->rxmaxdma);
4722 }
4723 
4724 
4725 /*
4726  * Gem kstat support
4727  */
4728 
4729 #define	GEM_LOCAL_DATA_SIZE(gc)	\
4730 	(sizeof (struct gem_dev) + \
4731 	sizeof (struct mcast_addr) * GEM_MAXMC + \
4732 	sizeof (struct txbuf) * ((gc)->gc_tx_buf_size) + \
4733 	sizeof (void *) * ((gc)->gc_tx_buf_size))
4734 
4735 struct gem_dev *
4736 gem_do_attach(dev_info_t *dip, int port,
4737 	struct gem_conf *gc, void *base, ddi_acc_handle_t *regs_handlep,
4738 	void *lp, int lmsize)
4739 {
4740 	struct gem_dev		*dp;
4741 	int			i;
4742 	ddi_iblock_cookie_t	c;
4743 	mac_register_t		*macp = NULL;
4744 	int			ret;
4745 	int			unit;
4746 	int			nports;
4747 
4748 	unit = ddi_get_instance(dip);
4749 	if ((nports = gc->gc_nports) == 0) {
4750 		nports = 1;
4751 	}
4752 	if (nports == 1) {
4753 		ddi_set_driver_private(dip, NULL);
4754 	}
4755 
4756 	DPRINTF(2, (CE_CONT, "!gem%d: gem_do_attach: called cmd:ATTACH",
4757 	    unit));
4758 
4759 	/*
4760 	 * Allocate soft data structure
4761 	 */
4762 	dp = kmem_zalloc(GEM_LOCAL_DATA_SIZE(gc), KM_SLEEP);
4763 
4764 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
4765 		cmn_err(CE_WARN, "!gem%d: %s: mac_alloc failed",
4766 		    unit, __func__);
4767 		return (NULL);
4768 	}
4769 	/* ddi_set_driver_private(dip, dp); */
4770 
4771 	/* link to private area */
4772 	dp->private = lp;
4773 	dp->priv_size = lmsize;
4774 	dp->mc_list = (struct mcast_addr *)&dp[1];
4775 
4776 	dp->dip = dip;
4777 	(void) sprintf(dp->name, gc->gc_name, nports * unit + port);
4778 
4779 	/*
4780 	 * Get iblock cookie
4781 	 */
4782 	if (ddi_get_iblock_cookie(dip, 0, &c) != DDI_SUCCESS) {
4783 		cmn_err(CE_CONT,
4784 		    "!%s: gem_do_attach: ddi_get_iblock_cookie: failed",
4785 		    dp->name);
4786 		goto err_free_private;
4787 	}
4788 	dp->iblock_cookie = c;
4789 
4790 	/*
4791 	 * Initialize mutex's for this device.
4792 	 */
4793 	mutex_init(&dp->intrlock, NULL, MUTEX_DRIVER, (void *)c);
4794 	mutex_init(&dp->xmitlock, NULL, MUTEX_DRIVER, (void *)c);
4795 	cv_init(&dp->tx_drain_cv, NULL, CV_DRIVER, NULL);
4796 
4797 	/*
4798 	 * configure gem parameter
4799 	 */
4800 	dp->base_addr = base;
4801 	dp->regs_handle = *regs_handlep;
4802 	dp->gc = *gc;
4803 	gc = &dp->gc;
4804 	/* patch for simplify dma resource management */
4805 	gc->gc_tx_max_frags = 1;
4806 	gc->gc_tx_max_descs_per_pkt = 1;
4807 	gc->gc_tx_ring_size = gc->gc_tx_buf_size;
4808 	gc->gc_tx_ring_limit = gc->gc_tx_buf_limit;
4809 	gc->gc_tx_desc_write_oo = B_TRUE;
4810 
4811 	gc->gc_nports = nports;	/* fix nports */
4812 
4813 	/* fix copy threadsholds */
4814 	gc->gc_tx_copy_thresh = max(ETHERMIN, gc->gc_tx_copy_thresh);
4815 	gc->gc_rx_copy_thresh = max(ETHERMIN, gc->gc_rx_copy_thresh);
4816 
4817 	/* fix rx buffer boundary for iocache line size */
4818 	ASSERT(gc->gc_dma_attr_txbuf.dma_attr_align-1 == gc->gc_tx_buf_align);
4819 	ASSERT(gc->gc_dma_attr_rxbuf.dma_attr_align-1 == gc->gc_rx_buf_align);
4820 	gc->gc_rx_buf_align = max(gc->gc_rx_buf_align, IOC_LINESIZE - 1);
4821 	gc->gc_dma_attr_rxbuf.dma_attr_align = gc->gc_rx_buf_align + 1;
4822 
4823 	/* fix descriptor boundary for cache line size */
4824 	gc->gc_dma_attr_desc.dma_attr_align =
4825 	    max(gc->gc_dma_attr_desc.dma_attr_align, IOC_LINESIZE);
4826 
4827 	/* patch get_packet method */
4828 	if (gc->gc_get_packet == NULL) {
4829 		gc->gc_get_packet = &gem_get_packet_default;
4830 	}
4831 
4832 	/* patch get_rx_start method */
4833 	if (gc->gc_rx_start == NULL) {
4834 		gc->gc_rx_start = &gem_rx_start_default;
4835 	}
4836 
4837 	/* calculate descriptor area */
4838 	if (gc->gc_rx_desc_unit_shift >= 0) {
4839 		dp->rx_desc_size =
4840 		    ROUNDUP(gc->gc_rx_ring_size << gc->gc_rx_desc_unit_shift,
4841 		    gc->gc_dma_attr_desc.dma_attr_align);
4842 	}
4843 	if (gc->gc_tx_desc_unit_shift >= 0) {
4844 		dp->tx_desc_size =
4845 		    ROUNDUP(gc->gc_tx_ring_size << gc->gc_tx_desc_unit_shift,
4846 		    gc->gc_dma_attr_desc.dma_attr_align);
4847 	}
4848 
4849 	dp->mtu = ETHERMTU;
4850 	dp->tx_buf = (void *)&dp->mc_list[GEM_MAXMC];
4851 	/* link tx buffers */
4852 	for (i = 0; i < dp->gc.gc_tx_buf_size; i++) {
4853 		dp->tx_buf[i].txb_next =
4854 		    &dp->tx_buf[SLOT(i + 1, dp->gc.gc_tx_buf_size)];
4855 	}
4856 
4857 	dp->rxmode	   = 0;
4858 	dp->speed	   = GEM_SPD_10;	/* default is 10Mbps */
4859 	dp->full_duplex    = B_FALSE;		/* default is half */
4860 	dp->flow_control   = FLOW_CONTROL_NONE;
4861 	dp->poll_pkt_delay = 8;		/* typical coalease for rx packets */
4862 
4863 	/* performance tuning parameters */
4864 	dp->txthr    = ETHERMAX;	/* tx fifo threshold */
4865 	dp->txmaxdma = 16*4;		/* tx max dma burst size */
4866 	dp->rxthr    = 128;		/* rx fifo threshold */
4867 	dp->rxmaxdma = 16*4;		/* rx max dma burst size */
4868 
4869 	/*
4870 	 * Get media mode information from .conf file
4871 	 */
4872 	gem_read_conf(dp);
4873 
4874 	/* rx_buf_len is required buffer length without padding for alignment */
4875 	dp->rx_buf_len = MAXPKTBUF(dp) + dp->gc.gc_rx_header_len;
4876 
4877 	/*
4878 	 * Reset the chip
4879 	 */
4880 	mutex_enter(&dp->intrlock);
4881 	dp->nic_state = NIC_STATE_STOPPED;
4882 	ret = (*dp->gc.gc_reset_chip)(dp);
4883 	mutex_exit(&dp->intrlock);
4884 	if (ret != GEM_SUCCESS) {
4885 		goto err_free_regs;
4886 	}
4887 
4888 	/*
4889 	 * HW dependant paremeter initialization
4890 	 */
4891 	mutex_enter(&dp->intrlock);
4892 	ret = (*dp->gc.gc_attach_chip)(dp);
4893 	mutex_exit(&dp->intrlock);
4894 	if (ret != GEM_SUCCESS) {
4895 		goto err_free_regs;
4896 	}
4897 
4898 #ifdef DEBUG_MULTIFRAGS
4899 	dp->gc.gc_tx_copy_thresh = dp->mtu;
4900 #endif
4901 	/* allocate tx and rx resources */
4902 	if (gem_alloc_memory(dp)) {
4903 		goto err_free_regs;
4904 	}
4905 
4906 	DPRINTF(0, (CE_CONT,
4907 	    "!%s: at 0x%x, %02x:%02x:%02x:%02x:%02x:%02x",
4908 	    dp->name, (long)dp->base_addr,
4909 	    dp->dev_addr.ether_addr_octet[0],
4910 	    dp->dev_addr.ether_addr_octet[1],
4911 	    dp->dev_addr.ether_addr_octet[2],
4912 	    dp->dev_addr.ether_addr_octet[3],
4913 	    dp->dev_addr.ether_addr_octet[4],
4914 	    dp->dev_addr.ether_addr_octet[5]));
4915 
4916 	/* copy mac address */
4917 	dp->cur_addr = dp->dev_addr;
4918 
4919 	gem_gld3_init(dp, macp);
4920 
4921 	/* Probe MII phy (scan phy) */
4922 	dp->mii_lpable = 0;
4923 	dp->mii_advert = 0;
4924 	dp->mii_exp = 0;
4925 	dp->mii_ctl1000 = 0;
4926 	dp->mii_stat1000 = 0;
4927 	if ((*dp->gc.gc_mii_probe)(dp) != GEM_SUCCESS) {
4928 		goto err_free_ring;
4929 	}
4930 
4931 	/* mask unsupported abilities */
4932 	dp->anadv_autoneg &= BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4933 	dp->anadv_1000fdx &=
4934 	    BOOLEAN(dp->mii_xstatus &
4935 	    (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD));
4936 	dp->anadv_1000hdx &=
4937 	    BOOLEAN(dp->mii_xstatus &
4938 	    (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET));
4939 	dp->anadv_100t4  &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
4940 	dp->anadv_100fdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4941 	dp->anadv_100hdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4942 	dp->anadv_10fdx  &= BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4943 	dp->anadv_10hdx  &= BOOLEAN(dp->mii_status & MII_STATUS_10);
4944 
4945 	gem_choose_forcedmode(dp);
4946 
4947 	/* initialize MII phy if required */
4948 	if (dp->gc.gc_mii_init) {
4949 		if ((*dp->gc.gc_mii_init)(dp) != GEM_SUCCESS) {
4950 			goto err_free_ring;
4951 		}
4952 	}
4953 
4954 	/*
4955 	 * initialize kstats including mii statistics
4956 	 */
4957 	gem_nd_setup(dp);
4958 
4959 	/*
4960 	 * Add interrupt to system.
4961 	 */
4962 	if (ret = mac_register(macp, &dp->mh)) {
4963 		cmn_err(CE_WARN, "!%s: mac_register failed, error:%d",
4964 		    dp->name, ret);
4965 		goto err_release_stats;
4966 	}
4967 	mac_free(macp);
4968 	macp = NULL;
4969 
4970 	if (dp->misc_flag & GEM_SOFTINTR) {
4971 		if (ddi_add_softintr(dip,
4972 		    DDI_SOFTINT_LOW, &dp->soft_id,
4973 		    NULL, NULL,
4974 		    (uint_t (*)(caddr_t))gem_intr,
4975 		    (caddr_t)dp) != DDI_SUCCESS) {
4976 			cmn_err(CE_WARN, "!%s: ddi_add_softintr failed",
4977 			    dp->name);
4978 			goto err_unregister;
4979 		}
4980 	} else if ((dp->misc_flag & GEM_NOINTR) == 0) {
4981 		if (ddi_add_intr(dip, 0, NULL, NULL,
4982 		    (uint_t (*)(caddr_t))gem_intr,
4983 		    (caddr_t)dp) != DDI_SUCCESS) {
4984 			cmn_err(CE_WARN, "!%s: ddi_add_intr failed", dp->name);
4985 			goto err_unregister;
4986 		}
4987 	} else {
4988 		/*
4989 		 * Dont use interrupt.
4990 		 * schedule first call of gem_intr_watcher
4991 		 */
4992 		dp->intr_watcher_id =
4993 		    timeout((void (*)(void *))gem_intr_watcher,
4994 		    (void *)dp, drv_usectohz(3*1000000));
4995 	}
4996 
4997 	/* link this device to dev_info */
4998 	dp->next = (struct gem_dev *)ddi_get_driver_private(dip);
4999 	dp->port = port;
5000 	ddi_set_driver_private(dip, (caddr_t)dp);
5001 
5002 	/* reset mii phy and start mii link watcher */
5003 	gem_mii_start(dp);
5004 
5005 	DPRINTF(2, (CE_CONT, "!gem_do_attach: return: success"));
5006 	return (dp);
5007 
5008 err_unregister:
5009 	(void) mac_unregister(dp->mh);
5010 err_release_stats:
5011 	/* release NDD resources */
5012 	gem_nd_cleanup(dp);
5013 
5014 err_free_ring:
5015 	gem_free_memory(dp);
5016 err_free_regs:
5017 	ddi_regs_map_free(&dp->regs_handle);
5018 err_free_locks:
5019 	mutex_destroy(&dp->xmitlock);
5020 	mutex_destroy(&dp->intrlock);
5021 	cv_destroy(&dp->tx_drain_cv);
5022 err_free_private:
5023 	if (macp) {
5024 		mac_free(macp);
5025 	}
5026 	kmem_free((caddr_t)dp, GEM_LOCAL_DATA_SIZE(gc));
5027 
5028 	return (NULL);
5029 }
5030 
5031 int
5032 gem_do_detach(dev_info_t *dip)
5033 {
5034 	struct gem_dev	*dp;
5035 	struct gem_dev	*tmp;
5036 	caddr_t		private;
5037 	int		priv_size;
5038 	ddi_acc_handle_t	rh;
5039 
5040 	dp = GEM_GET_DEV(dip);
5041 	if (dp == NULL) {
5042 		return (DDI_SUCCESS);
5043 	}
5044 
5045 	rh = dp->regs_handle;
5046 	private = dp->private;
5047 	priv_size = dp->priv_size;
5048 
5049 	while (dp) {
5050 		/* unregister with gld v3 */
5051 		if (mac_unregister(dp->mh) != 0) {
5052 			return (DDI_FAILURE);
5053 		}
5054 
5055 		/* ensure any rx buffers are not used */
5056 		if (dp->rx_buf_allocated != dp->rx_buf_freecnt) {
5057 			/* resource is busy */
5058 			cmn_err(CE_PANIC,
5059 			    "!%s: %s: rxbuf is busy: allocated:%d, freecnt:%d",
5060 			    dp->name, __func__,
5061 			    dp->rx_buf_allocated, dp->rx_buf_freecnt);
5062 			/* NOT REACHED */
5063 		}
5064 
5065 		/* stop mii link watcher */
5066 		gem_mii_stop(dp);
5067 
5068 		/* unregister interrupt handler */
5069 		if (dp->misc_flag & GEM_SOFTINTR) {
5070 			ddi_remove_softintr(dp->soft_id);
5071 		} else if ((dp->misc_flag & GEM_NOINTR) == 0) {
5072 			ddi_remove_intr(dip, 0, dp->iblock_cookie);
5073 		} else {
5074 			/* stop interrupt watcher */
5075 			if (dp->intr_watcher_id) {
5076 				while (untimeout(dp->intr_watcher_id) == -1)
5077 					;
5078 				dp->intr_watcher_id = 0;
5079 			}
5080 		}
5081 
5082 		/* release NDD resources */
5083 		gem_nd_cleanup(dp);
5084 		/* release buffers, descriptors and dma resources */
5085 		gem_free_memory(dp);
5086 
5087 		/* release locks and condition variables */
5088 		mutex_destroy(&dp->xmitlock);
5089 		mutex_destroy(&dp->intrlock);
5090 		cv_destroy(&dp->tx_drain_cv);
5091 
5092 		/* release basic memory resources */
5093 		tmp = dp->next;
5094 		kmem_free((caddr_t)dp, GEM_LOCAL_DATA_SIZE(&dp->gc));
5095 		dp = tmp;
5096 	}
5097 
5098 	/* release common private memory for the nic */
5099 	kmem_free(private, priv_size);
5100 
5101 	/* release register mapping resources */
5102 	ddi_regs_map_free(&rh);
5103 
5104 	DPRINTF(2, (CE_CONT, "!%s%d: gem_do_detach: return: success",
5105 	    ddi_driver_name(dip), ddi_get_instance(dip)));
5106 
5107 	return (DDI_SUCCESS);
5108 }
5109 
5110 int
5111 gem_suspend(dev_info_t *dip)
5112 {
5113 	struct gem_dev	*dp;
5114 
5115 	/*
5116 	 * stop the device
5117 	 */
5118 	dp = GEM_GET_DEV(dip);
5119 	ASSERT(dp);
5120 
5121 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
5122 
5123 	for (; dp; dp = dp->next) {
5124 
5125 		/* stop mii link watcher */
5126 		gem_mii_stop(dp);
5127 
5128 		/* stop interrupt watcher for no-intr mode */
5129 		if (dp->misc_flag & GEM_NOINTR) {
5130 			if (dp->intr_watcher_id) {
5131 				while (untimeout(dp->intr_watcher_id) == -1)
5132 					;
5133 			}
5134 			dp->intr_watcher_id = 0;
5135 		}
5136 
5137 		/* stop tx timeout watcher */
5138 		if (dp->timeout_id) {
5139 			while (untimeout(dp->timeout_id) == -1)
5140 				;
5141 			dp->timeout_id = 0;
5142 		}
5143 
5144 		/* make the nic state inactive */
5145 		mutex_enter(&dp->intrlock);
5146 		(void) gem_mac_stop(dp, 0);
5147 		ASSERT(!dp->mac_active);
5148 
5149 		/* no further register access */
5150 		dp->mac_suspended = B_TRUE;
5151 		mutex_exit(&dp->intrlock);
5152 	}
5153 
5154 	/* XXX - power down the nic */
5155 
5156 	return (DDI_SUCCESS);
5157 }
5158 
5159 int
5160 gem_resume(dev_info_t *dip)
5161 {
5162 	struct gem_dev	*dp;
5163 
5164 	/*
5165 	 * restart the device
5166 	 */
5167 	dp = GEM_GET_DEV(dip);
5168 	ASSERT(dp);
5169 
5170 	DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
5171 
5172 	for (; dp; dp = dp->next) {
5173 
5174 		/*
5175 		 * Bring up the nic after power up
5176 		 */
5177 
5178 		/* gem_xxx.c layer to setup power management state. */
5179 		ASSERT(!dp->mac_active);
5180 
5181 		/* reset the chip, because we are just after power up. */
5182 		mutex_enter(&dp->intrlock);
5183 
5184 		dp->mac_suspended = B_FALSE;
5185 		dp->nic_state = NIC_STATE_STOPPED;
5186 
5187 		if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
5188 			cmn_err(CE_WARN, "%s: %s: failed to reset chip",
5189 			    dp->name, __func__);
5190 			mutex_exit(&dp->intrlock);
5191 			goto err;
5192 		}
5193 		mutex_exit(&dp->intrlock);
5194 
5195 		/* initialize mii phy because we are just after power up */
5196 		if (dp->gc.gc_mii_init) {
5197 			(void) (*dp->gc.gc_mii_init)(dp);
5198 		}
5199 
5200 		if (dp->misc_flag & GEM_NOINTR) {
5201 			/*
5202 			 * schedule first call of gem_intr_watcher
5203 			 * instead of interrupts.
5204 			 */
5205 			dp->intr_watcher_id =
5206 			    timeout((void (*)(void *))gem_intr_watcher,
5207 			    (void *)dp, drv_usectohz(3*1000000));
5208 		}
5209 
5210 		/* restart mii link watcher */
5211 		gem_mii_start(dp);
5212 
5213 		/* restart mac */
5214 		mutex_enter(&dp->intrlock);
5215 
5216 		if (gem_mac_init(dp) != GEM_SUCCESS) {
5217 			mutex_exit(&dp->intrlock);
5218 			goto err_reset;
5219 		}
5220 		dp->nic_state = NIC_STATE_INITIALIZED;
5221 
5222 		/* setup media mode if the link have been up */
5223 		if (dp->mii_state == MII_STATE_LINKUP) {
5224 			if ((dp->gc.gc_set_media)(dp) != GEM_SUCCESS) {
5225 				mutex_exit(&dp->intrlock);
5226 				goto err_reset;
5227 			}
5228 		}
5229 
5230 		/* enable mac address and rx filter */
5231 		dp->rxmode |= RXMODE_ENABLE;
5232 		if ((*dp->gc.gc_set_rx_filter)(dp) != GEM_SUCCESS) {
5233 			mutex_exit(&dp->intrlock);
5234 			goto err_reset;
5235 		}
5236 		dp->nic_state = NIC_STATE_ONLINE;
5237 
5238 		/* restart tx timeout watcher */
5239 		dp->timeout_id = timeout((void (*)(void *))gem_tx_timeout,
5240 		    (void *)dp,
5241 		    dp->gc.gc_tx_timeout_interval);
5242 
5243 		/* now the nic is fully functional */
5244 		if (dp->mii_state == MII_STATE_LINKUP) {
5245 			if (gem_mac_start(dp) != GEM_SUCCESS) {
5246 				mutex_exit(&dp->intrlock);
5247 				goto err_reset;
5248 			}
5249 		}
5250 		mutex_exit(&dp->intrlock);
5251 	}
5252 
5253 	return (DDI_SUCCESS);
5254 
5255 err_reset:
5256 	if (dp->intr_watcher_id) {
5257 		while (untimeout(dp->intr_watcher_id) == -1)
5258 			;
5259 		dp->intr_watcher_id = 0;
5260 	}
5261 	mutex_enter(&dp->intrlock);
5262 	(*dp->gc.gc_reset_chip)(dp);
5263 	dp->nic_state = NIC_STATE_STOPPED;
5264 	mutex_exit(&dp->intrlock);
5265 
5266 err:
5267 	return (DDI_FAILURE);
5268 }
5269 
5270 /*
5271  * misc routines for PCI
5272  */
5273 uint8_t
5274 gem_search_pci_cap(dev_info_t *dip,
5275 		ddi_acc_handle_t conf_handle, uint8_t target)
5276 {
5277 	uint8_t		pci_cap_ptr;
5278 	uint32_t	pci_cap;
5279 
5280 	/* search power management capablities */
5281 	pci_cap_ptr = pci_config_get8(conf_handle, PCI_CONF_CAP_PTR);
5282 	while (pci_cap_ptr) {
5283 		/* read pci capability header */
5284 		pci_cap = pci_config_get32(conf_handle, pci_cap_ptr);
5285 		if ((pci_cap & 0xff) == target) {
5286 			/* found */
5287 			break;
5288 		}
5289 		/* get next_ptr */
5290 		pci_cap_ptr = (pci_cap >> 8) & 0xff;
5291 	}
5292 	return (pci_cap_ptr);
5293 }
5294 
5295 int
5296 gem_pci_set_power_state(dev_info_t *dip,
5297 		ddi_acc_handle_t conf_handle, uint_t new_mode)
5298 {
5299 	uint8_t		pci_cap_ptr;
5300 	uint32_t	pmcsr;
5301 	uint_t		unit;
5302 	const char	*drv_name;
5303 
5304 	ASSERT(new_mode < 4);
5305 
5306 	unit = ddi_get_instance(dip);
5307 	drv_name = ddi_driver_name(dip);
5308 
5309 	/* search power management capablities */
5310 	pci_cap_ptr = gem_search_pci_cap(dip, conf_handle, PCI_CAP_ID_PM);
5311 
5312 	if (pci_cap_ptr == 0) {
5313 		cmn_err(CE_CONT,
5314 		    "!%s%d: doesn't have pci power management capability",
5315 		    drv_name, unit);
5316 		return (DDI_FAILURE);
5317 	}
5318 
5319 	/* read power management capabilities */
5320 	pmcsr = pci_config_get32(conf_handle, pci_cap_ptr + PCI_PMCSR);
5321 
5322 	DPRINTF(0, (CE_CONT,
5323 	    "!%s%d: pmc found at 0x%x: pmcsr: 0x%08x",
5324 	    drv_name, unit, pci_cap_ptr, pmcsr));
5325 
5326 	/*
5327 	 * Is the resuested power mode supported?
5328 	 */
5329 	/* not yet */
5330 
5331 	/*
5332 	 * move to new mode
5333 	 */
5334 	pmcsr = (pmcsr & ~PCI_PMCSR_STATE_MASK) | new_mode;
5335 	pci_config_put32(conf_handle, pci_cap_ptr + PCI_PMCSR, pmcsr);
5336 
5337 	return (DDI_SUCCESS);
5338 }
5339 
5340 /*
5341  * select suitable register for by specified address space or register
5342  * offset in PCI config space
5343  */
5344 int
5345 gem_pci_regs_map_setup(dev_info_t *dip, uint32_t which, uint32_t mask,
5346 	struct ddi_device_acc_attr *attrp,
5347 	caddr_t *basep, ddi_acc_handle_t *hp)
5348 {
5349 	struct pci_phys_spec	*regs;
5350 	uint_t		len;
5351 	uint_t		unit;
5352 	uint_t		n;
5353 	uint_t		i;
5354 	int		ret;
5355 	const char	*drv_name;
5356 
5357 	unit = ddi_get_instance(dip);
5358 	drv_name = ddi_driver_name(dip);
5359 
5360 	/* Search IO-range or memory-range to be mapped */
5361 	regs = NULL;
5362 	len  = 0;
5363 
5364 	if ((ret = ddi_prop_lookup_int_array(
5365 	    DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
5366 	    "reg", (void *)&regs, &len)) != DDI_PROP_SUCCESS) {
5367 		cmn_err(CE_WARN,
5368 		    "!%s%d: failed to get reg property (ret:%d)",
5369 		    drv_name, unit, ret);
5370 		return (DDI_FAILURE);
5371 	}
5372 	n = len / (sizeof (struct pci_phys_spec) / sizeof (int));
5373 
5374 	ASSERT(regs != NULL && len > 0);
5375 
5376 #if GEM_DEBUG_LEVEL > 0
5377 	for (i = 0; i < n; i++) {
5378 		cmn_err(CE_CONT,
5379 		    "!%s%d: regs[%d]: %08x.%08x.%08x.%08x.%08x",
5380 		    drv_name, unit, i,
5381 		    regs[i].pci_phys_hi,
5382 		    regs[i].pci_phys_mid,
5383 		    regs[i].pci_phys_low,
5384 		    regs[i].pci_size_hi,
5385 		    regs[i].pci_size_low);
5386 	}
5387 #endif
5388 	for (i = 0; i < n; i++) {
5389 		if ((regs[i].pci_phys_hi & mask) == which) {
5390 			/* it's the requested space */
5391 			ddi_prop_free(regs);
5392 			goto address_range_found;
5393 		}
5394 	}
5395 	ddi_prop_free(regs);
5396 	return (DDI_FAILURE);
5397 
5398 address_range_found:
5399 	if ((ret = ddi_regs_map_setup(dip, i, basep, 0, 0, attrp, hp))
5400 	    != DDI_SUCCESS) {
5401 		cmn_err(CE_CONT,
5402 		    "!%s%d: ddi_regs_map_setup failed (ret:%d)",
5403 		    drv_name, unit, ret);
5404 	}
5405 
5406 	return (ret);
5407 }
5408 
5409 void
5410 gem_mod_init(struct dev_ops *dop, char *name)
5411 {
5412 	mac_init_ops(dop, name);
5413 }
5414 
5415 void
5416 gem_mod_fini(struct dev_ops *dop)
5417 {
5418 	mac_fini_ops(dop);
5419 }
5420