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