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