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