xref: /illumos-gate/usr/src/uts/common/io/mxfe/mxfe.c (revision f998c95e3b7029fe5f7542e115f7474ddb8024d7)
1 /*
2  * Solaris driver for ethernet cards based on the Macronix 98715
3  *
4  * Copyright (c) 2007 by Garrett D'Amore <garrett@damore.org>.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the author nor the names of any co-contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #include <sys/varargs.h>
35 #include <sys/types.h>
36 #include <sys/modctl.h>
37 #include <sys/conf.h>
38 #include <sys/devops.h>
39 #include <sys/stream.h>
40 #include <sys/strsun.h>
41 #include <sys/cmn_err.h>
42 #include <sys/dlpi.h>
43 #include <sys/ethernet.h>
44 #include <sys/kmem.h>
45 #include <sys/time.h>
46 #include <sys/miiregs.h>
47 #include <sys/strsun.h>
48 #include <sys/priv.h>
49 #include <sys/policy.h>
50 #include <sys/cred.h>
51 #include <sys/mac.h>
52 #include <sys/mac_ether.h>
53 #include <sys/ddi.h>
54 #include <sys/sunddi.h>
55 #include <sys/vlan.h>
56 
57 #include "mxfe.h"
58 #include "mxfeimpl.h"
59 
60 /*
61  * Driver globals.
62  */
63 
64 /* patchable debug flag ... must not be static! */
65 #ifdef	DEBUG
66 unsigned		mxfe_debug = DWARN;
67 #endif
68 
69 /* table of supported devices */
70 static mxfe_card_t mxfe_cards[] = {
71 
72 	/*
73 	 * Lite-On products
74 	 */
75 	{ 0x11ad, 0xc115, 0, 0, "Lite-On LC82C115", MXFE_PNICII },
76 
77 	/*
78 	 * Macronix chips
79 	 */
80 	{ 0x10d9, 0x0531, 0x25, 0xff, "Macronix MX98715AEC", MXFE_98715AEC },
81 	{ 0x10d9, 0x0531, 0x20, 0xff, "Macronix MX98715A", MXFE_98715A },
82 	{ 0x10d9, 0x0531, 0x60, 0xff, "Macronix MX98715B", MXFE_98715B },
83 	{ 0x10d9, 0x0531, 0x30, 0xff, "Macronix MX98725", MXFE_98725 },
84 	{ 0x10d9, 0x0531, 0x00, 0xff, "Macronix MX98715", MXFE_98715 },
85 	{ 0x10d9, 0x0512, 0, 0, "Macronix MX98713", MXFE_98713 },
86 
87 	/*
88 	 * Compex (relabeled Macronix products)
89 	 */
90 	{ 0x11fc, 0x9881, 0x00, 0x00, "Compex 9881", MXFE_98713 },
91 	{ 0x11fc, 0x9881, 0x10, 0xff, "Compex 9881A", MXFE_98713A },
92 	/*
93 	 * Models listed here
94 	 */
95 	{ 0x11ad, 0xc001, 0, 0, "Linksys LNE100TX", MXFE_PNICII },
96 	{ 0x2646, 0x000b, 0, 0, "Kingston KNE111TX", MXFE_PNICII },
97 	{ 0x1154, 0x0308, 0, 0, "Buffalo LGY-PCI-TXL", MXFE_98715AEC },
98 };
99 
100 #define	ETHERVLANMTU	(ETHERMAX + 4)
101 
102 /*
103  * Function prototypes
104  */
105 static int	mxfe_attach(dev_info_t *, ddi_attach_cmd_t);
106 static int	mxfe_detach(dev_info_t *, ddi_detach_cmd_t);
107 static int	mxfe_resume(dev_info_t *);
108 static int	mxfe_m_unicst(void *, const uint8_t *);
109 static int	mxfe_m_multicst(void *, boolean_t, const uint8_t *);
110 static int	mxfe_m_promisc(void *, boolean_t);
111 static mblk_t	*mxfe_m_tx(void *, mblk_t *);
112 static int	mxfe_m_stat(void *, uint_t, uint64_t *);
113 static int	mxfe_m_start(void *);
114 static void	mxfe_m_stop(void *);
115 static void	mxfe_m_ioctl(void *, queue_t *, mblk_t *);
116 static unsigned	mxfe_intr(caddr_t);
117 static void	mxfe_startmac(mxfe_t *);
118 static void	mxfe_stopmac(mxfe_t *);
119 static void	mxfe_resetrings(mxfe_t *);
120 static boolean_t	mxfe_initialize(mxfe_t *);
121 static void	mxfe_startall(mxfe_t *);
122 static void	mxfe_stopall(mxfe_t *);
123 static void	mxfe_resetall(mxfe_t *);
124 static mxfe_txbuf_t *mxfe_alloctxbuf(mxfe_t *);
125 static void	mxfe_destroytxbuf(mxfe_txbuf_t *);
126 static mxfe_rxbuf_t *mxfe_allocrxbuf(mxfe_t *);
127 static void	mxfe_destroyrxbuf(mxfe_rxbuf_t *);
128 static void	mxfe_send_setup(mxfe_t *);
129 static boolean_t	mxfe_send(mxfe_t *, mblk_t *);
130 static int	mxfe_allocrxring(mxfe_t *);
131 static void	mxfe_freerxring(mxfe_t *);
132 static int	mxfe_alloctxring(mxfe_t *);
133 static void	mxfe_freetxring(mxfe_t *);
134 static void	mxfe_error(dev_info_t *, char *, ...);
135 static uint8_t	mxfe_sromwidth(mxfe_t *);
136 static uint16_t	mxfe_readsromword(mxfe_t *, unsigned);
137 static void	mxfe_readsrom(mxfe_t *, unsigned, unsigned, void *);
138 static void	mxfe_getfactaddr(mxfe_t *, uchar_t *);
139 static int	mxfe_miireadbit(mxfe_t *);
140 static void	mxfe_miiwritebit(mxfe_t *, int);
141 static void	mxfe_miitristate(mxfe_t *);
142 static unsigned	mxfe_miiread(mxfe_t *, int, int);
143 static void	mxfe_miiwrite(mxfe_t *, int, int, uint16_t);
144 static unsigned	mxfe_miireadgeneral(mxfe_t *, int, int);
145 static void	mxfe_miiwritegeneral(mxfe_t *, int, int, uint16_t);
146 static unsigned	mxfe_miiread98713(mxfe_t *, int, int);
147 static void	mxfe_miiwrite98713(mxfe_t *, int, int, uint16_t);
148 static void	mxfe_startphy(mxfe_t *);
149 static void	mxfe_stopphy(mxfe_t *);
150 static void	mxfe_startphymii(mxfe_t *);
151 static void	mxfe_startphynway(mxfe_t *);
152 static void	mxfe_startnway(mxfe_t *);
153 static void	mxfe_reportlink(mxfe_t *);
154 static void	mxfe_checklink(mxfe_t *);
155 static void	mxfe_checklinkmii(mxfe_t *);
156 static void	mxfe_checklinknway(mxfe_t *);
157 static void	mxfe_disableinterrupts(mxfe_t *);
158 static void	mxfe_enableinterrupts(mxfe_t *);
159 static void	mxfe_reclaim(mxfe_t *);
160 static mblk_t	*mxfe_receive(mxfe_t *);
161 static int	mxfe_ndaddbytes(mblk_t *, char *, int);
162 static int	mxfe_ndaddstr(mblk_t *, char *, int);
163 static void	mxfe_ndparsestring(mblk_t *, char *, int);
164 static int	mxfe_ndparselen(mblk_t *);
165 static int	mxfe_ndparseint(mblk_t *);
166 static void	mxfe_ndget(mxfe_t *, queue_t *, mblk_t *);
167 static void	mxfe_ndset(mxfe_t *, queue_t *, mblk_t *);
168 static void	mxfe_ndfini(mxfe_t *);
169 static void	mxfe_ndinit(mxfe_t *);
170 static int	mxfe_ndquestion(mxfe_t *, mblk_t *, mxfe_nd_t *);
171 static int	mxfe_ndgetint(mxfe_t *, mblk_t *, mxfe_nd_t *);
172 static int	mxfe_ndgetbit(mxfe_t *, mblk_t *, mxfe_nd_t *);
173 static int	mxfe_ndsetadv(mxfe_t *, mblk_t *, mxfe_nd_t *);
174 static mxfe_nd_t *mxfe_ndfind(mxfe_t *, char *);
175 static void	mxfe_ndempty(mblk_t *);
176 static void	mxfe_ndadd(mxfe_t *, char *, mxfe_nd_pf_t, mxfe_nd_pf_t,
177     intptr_t, intptr_t);
178 
179 #ifdef	DEBUG
180 static void	mxfe_dprintf(mxfe_t *, const char *, int, char *, ...);
181 #endif
182 
183 #define	KIOIP	KSTAT_INTR_PTR(mxfep->mxfe_intrstat)
184 
185 static mac_callbacks_t mxfe_m_callbacks = {
186 	MC_IOCTL,
187 	mxfe_m_stat,
188 	mxfe_m_start,
189 	mxfe_m_stop,
190 	mxfe_m_promisc,
191 	mxfe_m_multicst,
192 	mxfe_m_unicst,
193 	mxfe_m_tx,
194 	NULL,
195 	mxfe_m_ioctl,
196 	NULL,		/* m_getcapab */
197 };
198 
199 /*
200  * Stream information
201  */
202 DDI_DEFINE_STREAM_OPS(mxfe_devops, nulldev, nulldev, mxfe_attach, mxfe_detach,
203     nodev, NULL, D_MP, NULL);
204 
205 /*
206  * Module linkage information.
207  */
208 
209 static struct modldrv mxfe_modldrv = {
210 	&mod_driverops,			/* drv_modops */
211 	"Macronix Fast Ethernet",	/* drv_linkinfo */
212 	&mxfe_devops			/* drv_dev_ops */
213 };
214 
215 static struct modlinkage mxfe_modlinkage = {
216 	MODREV_1,		/* ml_rev */
217 	{ &mxfe_modldrv, NULL } /* ml_linkage */
218 };
219 
220 /*
221  * Device attributes.
222  */
223 static ddi_device_acc_attr_t mxfe_devattr = {
224 	DDI_DEVICE_ATTR_V0,
225 	DDI_STRUCTURE_LE_ACC,
226 	DDI_STRICTORDER_ACC
227 };
228 
229 static ddi_device_acc_attr_t mxfe_bufattr = {
230 	DDI_DEVICE_ATTR_V0,
231 	DDI_NEVERSWAP_ACC,
232 	DDI_STRICTORDER_ACC
233 };
234 
235 static ddi_dma_attr_t mxfe_dma_attr = {
236 	DMA_ATTR_V0,		/* dma_attr_version */
237 	0,			/* dma_attr_addr_lo */
238 	0xFFFFFFFFU,		/* dma_attr_addr_hi */
239 	0x7FFFFFFFU,		/* dma_attr_count_max */
240 	4,			/* dma_attr_align */
241 	0x3F,			/* dma_attr_burstsizes */
242 	1,			/* dma_attr_minxfer */
243 	0xFFFFFFFFU,		/* dma_attr_maxxfer */
244 	0xFFFFFFFFU,		/* dma_attr_seg */
245 	1,			/* dma_attr_sgllen */
246 	1,			/* dma_attr_granular */
247 	0			/* dma_attr_flags */
248 };
249 
250 /*
251  * Tx buffers can be arbitrarily aligned.  Additionally, they can
252  * cross a page boundary, so we use the two buffer addresses of the
253  * chip to provide a two-entry scatter-gather list.
254  */
255 static ddi_dma_attr_t mxfe_dma_txattr = {
256 	DMA_ATTR_V0,		/* dma_attr_version */
257 	0,			/* dma_attr_addr_lo */
258 	0xFFFFFFFFU,		/* dma_attr_addr_hi */
259 	0x7FFFFFFFU,		/* dma_attr_count_max */
260 	1,			/* dma_attr_align */
261 	0x3F,			/* dma_attr_burstsizes */
262 	1,			/* dma_attr_minxfer */
263 	0xFFFFFFFFU,		/* dma_attr_maxxfer */
264 	0xFFFFFFFFU,		/* dma_attr_seg */
265 	2,			/* dma_attr_sgllen */
266 	1,			/* dma_attr_granular */
267 	0			/* dma_attr_flags */
268 };
269 
270 /*
271  * Ethernet addresses.
272  */
273 static uchar_t mxfe_broadcast[ETHERADDRL] = {
274 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
275 };
276 
277 /*
278  * DDI entry points.
279  */
280 int
281 _init(void)
282 {
283 	int	rv;
284 	mac_init_ops(&mxfe_devops, "mxfe");
285 	if ((rv = mod_install(&mxfe_modlinkage)) != DDI_SUCCESS) {
286 		mac_fini_ops(&mxfe_devops);
287 	}
288 	return (rv);
289 }
290 
291 int
292 _fini(void)
293 {
294 	int	rv;
295 	if ((rv = mod_remove(&mxfe_modlinkage)) == DDI_SUCCESS) {
296 		mac_fini_ops(&mxfe_devops);
297 	}
298 	return (rv);
299 }
300 
301 int
302 _info(struct modinfo *modinfop)
303 {
304 	return (mod_info(&mxfe_modlinkage, modinfop));
305 }
306 
307 int
308 mxfe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
309 {
310 	mxfe_t			*mxfep;
311 	mac_register_t		*macp;
312 	int			inst = ddi_get_instance(dip);
313 	ddi_acc_handle_t	pci;
314 	uint16_t		venid;
315 	uint16_t		devid;
316 	uint16_t		revid;
317 	uint16_t		svid;
318 	uint16_t		ssid;
319 	uint16_t		cachesize;
320 	mxfe_card_t		*cardp;
321 	int			i;
322 
323 	switch (cmd) {
324 	case DDI_RESUME:
325 		return (mxfe_resume(dip));
326 
327 	case DDI_ATTACH:
328 		break;
329 
330 	default:
331 		return (DDI_FAILURE);
332 	}
333 
334 	/* this card is a bus master, reject any slave-only slot */
335 	if (ddi_slaveonly(dip) == DDI_SUCCESS) {
336 		mxfe_error(dip, "slot does not support PCI bus-master");
337 		return (DDI_FAILURE);
338 	}
339 	/* PCI devices shouldn't generate hilevel interrupts */
340 	if (ddi_intr_hilevel(dip, 0) != 0) {
341 		mxfe_error(dip, "hilevel interrupts not supported");
342 		return (DDI_FAILURE);
343 	}
344 	if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
345 		mxfe_error(dip, "unable to setup PCI config handle");
346 		return (DDI_FAILURE);
347 	}
348 
349 	venid = pci_config_get16(pci, PCI_VID);
350 	devid = pci_config_get16(pci, PCI_DID);
351 	revid = pci_config_get16(pci, PCI_RID);
352 	svid = pci_config_get16(pci, PCI_SVID);
353 	ssid = pci_config_get16(pci, PCI_SSID);
354 
355 	/*
356 	 * the last entry in the card table matches every possible
357 	 * card, so the for-loop always terminates properly.
358 	 */
359 	cardp = NULL;
360 	for (i = 0; i < (sizeof (mxfe_cards) / sizeof (mxfe_card_t)); i++) {
361 		if ((venid == mxfe_cards[i].card_venid) &&
362 		    (devid == mxfe_cards[i].card_devid) &&
363 		    ((revid & mxfe_cards[i].card_revmask) ==
364 		    mxfe_cards[i].card_revid)) {
365 			cardp = &mxfe_cards[i];
366 		}
367 		if ((svid == mxfe_cards[i].card_venid) &&
368 		    (ssid == mxfe_cards[i].card_devid) &&
369 		    ((revid & mxfe_cards[i].card_revmask) ==
370 		    mxfe_cards[i].card_revid)) {
371 			cardp = &mxfe_cards[i];
372 			break;
373 		}
374 	}
375 
376 	if (cardp == NULL) {
377 		pci_config_teardown(&pci);
378 		mxfe_error(dip, "Unable to identify PCI card");
379 		return (DDI_FAILURE);
380 	}
381 
382 	if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
383 	    cardp->card_cardname) != DDI_PROP_SUCCESS) {
384 		pci_config_teardown(&pci);
385 		mxfe_error(dip, "Unable to create model property");
386 		return (DDI_FAILURE);
387 	}
388 
389 	/*
390 	 * Grab the PCI cachesize -- we use this to program the
391 	 * cache-optimization bus access bits.
392 	 */
393 	cachesize = pci_config_get8(pci, PCI_CLS);
394 
395 	/* this cannot fail */
396 	mxfep = kmem_zalloc(sizeof (mxfe_t), KM_SLEEP);
397 	ddi_set_driver_private(dip, mxfep);
398 
399 	/* get the interrupt block cookie */
400 	if (ddi_get_iblock_cookie(dip, 0, &mxfep->mxfe_icookie)
401 	    != DDI_SUCCESS) {
402 		mxfe_error(dip, "ddi_get_iblock_cookie failed");
403 		pci_config_teardown(&pci);
404 		kmem_free(mxfep, sizeof (mxfe_t));
405 		return (DDI_FAILURE);
406 	}
407 
408 	mxfep->mxfe_dip = dip;
409 	mxfep->mxfe_cardp = cardp;
410 	mxfep->mxfe_phyaddr = -1;
411 	mxfep->mxfe_cachesize = cachesize;
412 
413 	/* default properties */
414 	mxfep->mxfe_adv_aneg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
415 	    "adv_autoneg_cap", 1);
416 	mxfep->mxfe_adv_100T4 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
417 	    "adv_100T4_cap", 1);
418 	mxfep->mxfe_adv_100fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
419 	    "adv_100fdx_cap", 1);
420 	mxfep->mxfe_adv_100hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
421 	    "adv_100hdx_cap", 1);
422 	mxfep->mxfe_adv_10fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
423 	    "adv_10fdx_cap", 1);
424 	mxfep->mxfe_adv_10hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
425 	    "adv_10hdx_cap", 1);
426 
427 	DBG(DPCI, "PCI vendor id = %x", venid);
428 	DBG(DPCI, "PCI device id = %x", devid);
429 	DBG(DPCI, "PCI revision id = %x", revid);
430 	DBG(DPCI, "PCI cachesize = %d", cachesize);
431 	DBG(DPCI, "PCI COMM = %x", pci_config_get8(pci, PCI_CMD));
432 	DBG(DPCI, "PCI STAT = %x", pci_config_get8(pci, PCI_STAT));
433 
434 	mutex_init(&mxfep->mxfe_xmtlock, NULL, MUTEX_DRIVER,
435 	    mxfep->mxfe_icookie);
436 	mutex_init(&mxfep->mxfe_intrlock, NULL, MUTEX_DRIVER,
437 	    mxfep->mxfe_icookie);
438 
439 	mxfe_ndinit(mxfep);
440 
441 	/*
442 	 * Enable bus master, IO space, and memory space accesses.
443 	 */
444 	pci_config_put16(pci, PCI_CMD,
445 	    pci_config_get16(pci, PCI_CMD) |
446 	    PCI_CMD_BME | PCI_CMD_MAE | PCI_CMD_MWIE);
447 
448 	/* we're done with this now, drop it */
449 	pci_config_teardown(&pci);
450 
451 	/*
452 	 * Initialize interrupt kstat.  This should not normally fail, since
453 	 * we don't use a persistent stat.  We do it this way to avoid having
454 	 * to test for it at run time on the hot path.
455 	 */
456 	mxfep->mxfe_intrstat = kstat_create("mxfe", inst, "intr", "controller",
457 	    KSTAT_TYPE_INTR, 1, 0);
458 	if (mxfep->mxfe_intrstat == NULL) {
459 		mxfe_error(dip, "kstat_create failed");
460 		goto failed;
461 	}
462 	kstat_install(mxfep->mxfe_intrstat);
463 
464 	/*
465 	 * Map in the device registers.
466 	 */
467 	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&mxfep->mxfe_regs,
468 	    0, 0, &mxfe_devattr, &mxfep->mxfe_regshandle)) {
469 		mxfe_error(dip, "ddi_regs_map_setup failed");
470 		goto failed;
471 	}
472 
473 	/*
474 	 * Allocate DMA resources (descriptor rings and buffers).
475 	 */
476 	if ((mxfe_allocrxring(mxfep) != DDI_SUCCESS) ||
477 	    (mxfe_alloctxring(mxfep) != DDI_SUCCESS)) {
478 		mxfe_error(dip, "unable to allocate DMA resources");
479 		goto failed;
480 	}
481 
482 	/* Initialize the chip. */
483 	mutex_enter(&mxfep->mxfe_intrlock);
484 	mutex_enter(&mxfep->mxfe_xmtlock);
485 	if (!mxfe_initialize(mxfep)) {
486 		mutex_exit(&mxfep->mxfe_xmtlock);
487 		mutex_exit(&mxfep->mxfe_intrlock);
488 		goto failed;
489 	}
490 	mutex_exit(&mxfep->mxfe_xmtlock);
491 	mutex_exit(&mxfep->mxfe_intrlock);
492 
493 	/* Determine the number of address bits to our EEPROM. */
494 	mxfep->mxfe_sromwidth = mxfe_sromwidth(mxfep);
495 
496 	/*
497 	 * Get the factory ethernet address.  This becomes the current
498 	 * ethernet address (it can be overridden later via ifconfig).
499 	 */
500 	mxfe_getfactaddr(mxfep, mxfep->mxfe_curraddr);
501 	mxfep->mxfe_promisc = B_FALSE;
502 
503 	/*
504 	 * Establish interrupt handler.
505 	 */
506 	if (ddi_add_intr(dip, 0, NULL, NULL, mxfe_intr, (caddr_t)mxfep) !=
507 	    DDI_SUCCESS) {
508 		mxfe_error(dip, "unable to add interrupt");
509 		goto failed;
510 	}
511 
512 	/* TODO: do the power management stuff */
513 
514 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
515 		mxfe_error(dip, "mac_alloc failed");
516 		goto failed;
517 	}
518 
519 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
520 	macp->m_driver = mxfep;
521 	macp->m_dip = dip;
522 	macp->m_src_addr = mxfep->mxfe_curraddr;
523 	macp->m_callbacks = &mxfe_m_callbacks;
524 	macp->m_min_sdu = 0;
525 	macp->m_max_sdu = ETHERMTU;
526 	macp->m_margin = VLAN_TAGSZ;
527 
528 	if (mac_register(macp, &mxfep->mxfe_mh) == DDI_SUCCESS) {
529 		mac_free(macp);
530 		return (DDI_SUCCESS);
531 	}
532 
533 	/* failed to register with MAC */
534 	mac_free(macp);
535 failed:
536 	if (mxfep->mxfe_icookie != NULL) {
537 		ddi_remove_intr(dip, 0, mxfep->mxfe_icookie);
538 	}
539 	if (mxfep->mxfe_intrstat) {
540 		kstat_delete(mxfep->mxfe_intrstat);
541 	}
542 	mxfe_ndfini(mxfep);
543 	mutex_destroy(&mxfep->mxfe_intrlock);
544 	mutex_destroy(&mxfep->mxfe_xmtlock);
545 
546 	mxfe_freerxring(mxfep);
547 	mxfe_freetxring(mxfep);
548 
549 	if (mxfep->mxfe_regshandle != NULL) {
550 		ddi_regs_map_free(&mxfep->mxfe_regshandle);
551 	}
552 	kmem_free(mxfep, sizeof (mxfe_t));
553 	return (DDI_FAILURE);
554 }
555 
556 int
557 mxfe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
558 {
559 	mxfe_t		*mxfep;
560 
561 	mxfep = ddi_get_driver_private(dip);
562 	if (mxfep == NULL) {
563 		mxfe_error(dip, "no soft state in detach!");
564 		return (DDI_FAILURE);
565 	}
566 
567 	switch (cmd) {
568 	case DDI_DETACH:
569 
570 		if (mac_unregister(mxfep->mxfe_mh) != 0) {
571 			return (DDI_FAILURE);
572 		}
573 
574 		/* make sure hardware is quiesced */
575 		mutex_enter(&mxfep->mxfe_intrlock);
576 		mutex_enter(&mxfep->mxfe_xmtlock);
577 		mxfep->mxfe_flags &= ~MXFE_RUNNING;
578 		mxfe_stopall(mxfep);
579 		mutex_exit(&mxfep->mxfe_xmtlock);
580 		mutex_exit(&mxfep->mxfe_intrlock);
581 
582 		/* clean up and shut down device */
583 		ddi_remove_intr(dip, 0, mxfep->mxfe_icookie);
584 
585 		/* clean up kstats */
586 		kstat_delete(mxfep->mxfe_intrstat);
587 
588 		ddi_prop_remove_all(dip);
589 
590 		/* free up any left over buffers or DMA resources */
591 		mxfe_freerxring(mxfep);
592 		mxfe_freetxring(mxfep);
593 
594 		mxfe_ndfini(mxfep);
595 		ddi_regs_map_free(&mxfep->mxfe_regshandle);
596 		mutex_destroy(&mxfep->mxfe_intrlock);
597 		mutex_destroy(&mxfep->mxfe_xmtlock);
598 
599 		kmem_free(mxfep, sizeof (mxfe_t));
600 		return (DDI_SUCCESS);
601 
602 	case DDI_SUSPEND:
603 		/* quiesce the hardware */
604 		mutex_enter(&mxfep->mxfe_intrlock);
605 		mutex_enter(&mxfep->mxfe_xmtlock);
606 		mxfep->mxfe_flags |= MXFE_SUSPENDED;
607 		mxfe_stopall(mxfep);
608 		mutex_exit(&mxfep->mxfe_xmtlock);
609 		mutex_exit(&mxfep->mxfe_intrlock);
610 		return (DDI_SUCCESS);
611 	default:
612 		return (DDI_FAILURE);
613 	}
614 }
615 
616 int
617 mxfe_resume(dev_info_t *dip)
618 {
619 	mxfe_t		*mxfep;
620 
621 	if ((mxfep = ddi_get_driver_private(dip)) == NULL) {
622 		return (DDI_FAILURE);
623 	}
624 
625 	mutex_enter(&mxfep->mxfe_intrlock);
626 	mutex_enter(&mxfep->mxfe_xmtlock);
627 
628 	mxfep->mxfe_flags &= ~MXFE_SUSPENDED;
629 
630 	/* re-initialize chip */
631 	if (!mxfe_initialize(mxfep)) {
632 		mxfe_error(mxfep->mxfe_dip, "unable to resume chip!");
633 		mxfep->mxfe_flags |= MXFE_SUSPENDED;
634 		mutex_exit(&mxfep->mxfe_intrlock);
635 		mutex_exit(&mxfep->mxfe_xmtlock);
636 		return (DDI_SUCCESS);
637 	}
638 
639 	/* start the chip */
640 	if (mxfep->mxfe_flags & MXFE_RUNNING) {
641 		mxfe_startall(mxfep);
642 	}
643 
644 	/* drop locks */
645 	mutex_exit(&mxfep->mxfe_xmtlock);
646 	mutex_exit(&mxfep->mxfe_intrlock);
647 
648 	return (DDI_SUCCESS);
649 }
650 
651 void
652 mxfe_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
653 {
654 	mxfe_t *mxfep = arg;
655 
656 	switch (*(int *)(void *)(mp->b_rptr)) {
657 
658 	case NDIOC_GET:
659 		mxfe_ndget(mxfep, wq, mp);
660 		break;
661 
662 	case NDIOC_SET:
663 		mxfe_ndset(mxfep, wq, mp);
664 		break;
665 
666 	default:
667 		miocnak(wq, mp, 0, EINVAL);
668 		break;
669 	}
670 }
671 
672 /*ARGSUSED*/
673 int
674 mxfe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
675 {
676 	/* we already receive all multicast frames */
677 	return (0);
678 }
679 
680 int
681 mxfe_m_promisc(void *arg, boolean_t on)
682 {
683 	mxfe_t		*mxfep = arg;
684 
685 	/* exclusive access to the card while we reprogram it */
686 	mutex_enter(&mxfep->mxfe_intrlock);
687 	mutex_enter(&mxfep->mxfe_xmtlock);
688 	/* save current promiscuous mode state for replay in resume */
689 	mxfep->mxfe_promisc = on;
690 
691 	if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) ==
692 	    MXFE_RUNNING) {
693 		if (on)
694 			SETBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
695 		else
696 			CLRBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
697 	}
698 
699 	mutex_exit(&mxfep->mxfe_xmtlock);
700 	mutex_exit(&mxfep->mxfe_intrlock);
701 
702 	return (0);
703 }
704 
705 int
706 mxfe_m_unicst(void *arg, const uint8_t *macaddr)
707 {
708 	mxfe_t		*mxfep = arg;
709 
710 	mutex_enter(&mxfep->mxfe_intrlock);
711 	mutex_enter(&mxfep->mxfe_xmtlock);
712 	bcopy(macaddr, mxfep->mxfe_curraddr, ETHERADDRL);
713 
714 	mxfe_resetall(mxfep);
715 
716 	mutex_exit(&mxfep->mxfe_intrlock);
717 	mutex_exit(&mxfep->mxfe_xmtlock);
718 
719 	return (0);
720 }
721 
722 mblk_t *
723 mxfe_m_tx(void *arg, mblk_t *mp)
724 {
725 	mxfe_t	*mxfep = arg;
726 	mblk_t	*nmp;
727 
728 	mutex_enter(&mxfep->mxfe_xmtlock);
729 
730 	if (mxfep->mxfe_flags & MXFE_SUSPENDED) {
731 		mutex_exit(&mxfep->mxfe_xmtlock);
732 		return (mp);
733 	}
734 
735 	while (mp != NULL) {
736 		nmp = mp->b_next;
737 		mp->b_next = NULL;
738 
739 		if (!mxfe_send(mxfep, mp)) {
740 			mp->b_next = nmp;
741 			break;
742 		}
743 		mp = nmp;
744 	}
745 	mutex_exit(&mxfep->mxfe_xmtlock);
746 
747 	return (mp);
748 }
749 
750 /*
751  * Hardware management.
752  */
753 boolean_t
754 mxfe_initialize(mxfe_t *mxfep)
755 {
756 	int		i;
757 	unsigned	val;
758 	uint32_t	par, nar;
759 
760 	ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
761 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
762 
763 	DBG(DCHATTY, "resetting!");
764 	SETBIT(mxfep, CSR_PAR, PAR_RESET);
765 	for (i = 1; i < 10; i++) {
766 		drv_usecwait(5);
767 		val = GETCSR(mxfep, CSR_PAR);
768 		if (!(val & PAR_RESET)) {
769 			break;
770 		}
771 	}
772 	if (i == 10) {
773 		mxfe_error(mxfep->mxfe_dip, "timed out waiting for reset!");
774 		return (B_FALSE);
775 	}
776 
777 	/* initialize busctl register */
778 	par = PAR_BAR | PAR_MRME | PAR_MRLE | PAR_MWIE;
779 
780 	/* set the cache alignment if its supported */
781 	switch (mxfep->mxfe_cachesize) {
782 	case 8:
783 		par |= PAR_CALIGN_8;
784 		break;
785 	case 16:
786 		par |= PAR_CALIGN_16;
787 		break;
788 	case 32:
789 		par |= PAR_CALIGN_32;
790 		break;
791 	default:
792 		par &= ~(PAR_MWIE | PAR_MRME | PAR_MRLE);
793 	}
794 
795 	/* leave the burst length at zero, indicating infinite burst */
796 	PUTCSR(mxfep, CSR_PAR, par);
797 
798 	mxfe_resetrings(mxfep);
799 
800 	/* clear the lost packet counter (cleared on read) */
801 	(void) GETCSR(mxfep, CSR_LPC);
802 
803 	/* a few other NAR bits */
804 	nar = GETCSR(mxfep, CSR_NAR);
805 	nar &= ~NAR_RX_HO;	/* disable hash only filtering */
806 	nar |= NAR_RX_HP;	/* hash perfect forwarding */
807 	nar |= NAR_RX_MULTI;	/* receive all multicast */
808 	nar |= NAR_SF;	/* store-and-forward */
809 
810 	if (mxfep->mxfe_promisc) {
811 		nar |= NAR_RX_PROMISC;
812 	} else {
813 		nar &= ~NAR_RX_PROMISC;
814 	}
815 	PUTCSR(mxfep, CSR_NAR, nar);
816 
817 	mxfe_send_setup(mxfep);
818 
819 	return (B_TRUE);
820 }
821 
822 /*
823  * Serial EEPROM access - inspired by the FreeBSD implementation.
824  */
825 
826 uint8_t
827 mxfe_sromwidth(mxfe_t *mxfep)
828 {
829 	int		i;
830 	int		eeread;
831 	uint8_t		addrlen = 8;
832 
833 	eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
834 
835 	PUTCSR(mxfep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
836 	drv_usecwait(1);
837 	PUTCSR(mxfep, CSR_SPR, eeread);
838 
839 	/* command bits first */
840 	for (i = 4; i != 0; i >>= 1) {
841 		unsigned val = (SROM_READCMD & i) ? SPR_SROM_DIN : 0;
842 		PUTCSR(mxfep, CSR_SPR, eeread | val);
843 		drv_usecwait(1);
844 		PUTCSR(mxfep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
845 		drv_usecwait(1);
846 	}
847 
848 	PUTCSR(mxfep, CSR_SPR, eeread);
849 
850 	for (addrlen = 1; addrlen <= 12; addrlen++) {
851 		PUTCSR(mxfep, CSR_SPR, eeread | SPR_SROM_CLOCK);
852 		drv_usecwait(1);
853 		if (!(GETCSR(mxfep, CSR_SPR) & SPR_SROM_DOUT)) {
854 			PUTCSR(mxfep, CSR_SPR, eeread);
855 			drv_usecwait(1);
856 			break;
857 		}
858 		PUTCSR(mxfep, CSR_SPR, eeread);
859 		drv_usecwait(1);
860 	}
861 
862 	/* turn off accesses to the EEPROM */
863 	PUTCSR(mxfep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
864 
865 	DBG(DSROM, "detected srom width = %d bits", addrlen);
866 
867 	return ((addrlen < 4 || addrlen > 12) ? 6 : addrlen);
868 }
869 
870 /*
871  * The words in EEPROM are stored in little endian order.  We
872  * shift bits out in big endian order, though.  This requires
873  * a byte swap on some platforms.
874  */
875 uint16_t
876 mxfe_readsromword(mxfe_t *mxfep, unsigned romaddr)
877 {
878 	int		i;
879 	uint16_t	word = 0;
880 	uint16_t	retval;
881 	int		eeread;
882 	uint8_t		addrlen;
883 	int		readcmd;
884 	uchar_t		*ptr;
885 
886 	eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
887 	addrlen = mxfep->mxfe_sromwidth;
888 	readcmd = (SROM_READCMD << addrlen) | romaddr;
889 
890 	if (romaddr >= (1 << addrlen)) {
891 		/* too big to fit! */
892 		return (0);
893 	}
894 
895 	PUTCSR(mxfep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
896 	PUTCSR(mxfep, CSR_SPR, eeread);
897 
898 	/* command and address bits */
899 	for (i = 4 + addrlen; i >= 0; i--) {
900 		short val = (readcmd & (1 << i)) ?  SPR_SROM_DIN : 0;
901 		PUTCSR(mxfep, CSR_SPR, eeread | val);
902 		drv_usecwait(1);
903 		PUTCSR(mxfep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
904 		drv_usecwait(1);
905 	}
906 
907 	PUTCSR(mxfep, CSR_SPR, eeread);
908 
909 	for (i = 0; i < 16; i++) {
910 		PUTCSR(mxfep, CSR_SPR, eeread | SPR_SROM_CLOCK);
911 		drv_usecwait(1);
912 		word <<= 1;
913 		if (GETCSR(mxfep, CSR_SPR) & SPR_SROM_DOUT) {
914 			word |= 1;
915 		}
916 		PUTCSR(mxfep, CSR_SPR, eeread);
917 		drv_usecwait(1);
918 	}
919 
920 	/* turn off accesses to the EEPROM */
921 	PUTCSR(mxfep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
922 
923 	/*
924 	 * Fix up the endianness thing.  Note that the values
925 	 * are stored in little endian format on the SROM.
926 	 */
927 	DBG(DSROM, "got value %d from SROM (before swap)", word);
928 	ptr = (uchar_t *)&word;
929 	retval = (ptr[1] << 8) | ptr[0];
930 	return (retval);
931 }
932 
933 void
934 mxfe_readsrom(mxfe_t *mxfep, unsigned romaddr, unsigned len, void *dest)
935 {
936 	char		*ptr = dest;
937 	int		i;
938 	uint16_t	word;
939 
940 	for (i = 0; i < len; i++) {
941 		word = mxfe_readsromword(mxfep, romaddr + i);
942 		bcopy(&word, ptr, 2);
943 		ptr += 2;
944 		DBG(DSROM, "word at %d is 0x%x", romaddr + i, word);
945 	}
946 }
947 
948 void
949 mxfe_getfactaddr(mxfe_t *mxfep, uchar_t *eaddr)
950 {
951 	uint16_t	word;
952 	uchar_t		*ptr;
953 
954 	/* first read to get the location of mac address in srom */
955 	word = mxfe_readsromword(mxfep, SROM_ENADDR / 2);
956 	ptr = (uchar_t *)&word;
957 	word = (ptr[1] << 8) | ptr[0];
958 
959 	/* then read the actual mac address */
960 	mxfe_readsrom(mxfep, word / 2, ETHERADDRL / 2, eaddr);
961 	DBG(DMACID,
962 	    "factory ethernet address = %02x:%02x:%02x:%02x:%02x:%02x",
963 	    eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
964 }
965 
966 void
967 mxfe_startphy(mxfe_t *mxfep)
968 {
969 	switch (MXFE_MODEL(mxfep)) {
970 	case MXFE_98713A:
971 		mxfe_startphymii(mxfep);
972 		break;
973 	default:
974 		mxfe_startphynway(mxfep);
975 		break;
976 	}
977 }
978 
979 void
980 mxfe_stopphy(mxfe_t *mxfep)
981 {
982 	uint32_t	nar;
983 	int		i;
984 
985 	/* stop the phy timer */
986 	PUTCSR(mxfep, CSR_TIMER, 0);
987 
988 	switch (MXFE_MODEL(mxfep)) {
989 	case MXFE_98713A:
990 		for (i = 0; i < 32; i++) {
991 			mxfe_miiwrite(mxfep, mxfep->mxfe_phyaddr, MII_CONTROL,
992 			    MII_CONTROL_PWRDN | MII_CONTROL_ISOLATE);
993 		}
994 		break;
995 	default:
996 		DBG(DPHY, "resetting SIA");
997 		PUTCSR(mxfep, CSR_SIA, SIA_RESET);
998 		drv_usecwait(500);
999 		CLRBIT(mxfep, CSR_TCTL, TCTL_PWR | TCTL_ANE);
1000 		nar = GETCSR(mxfep, CSR_NAR);
1001 		nar &= ~(NAR_PORTSEL | NAR_PCS | NAR_SCR | NAR_FDX);
1002 		nar |= NAR_SPEED;
1003 		PUTCSR(mxfep, CSR_NAR, nar);
1004 		break;
1005 	}
1006 
1007 	/*
1008 	 * mark the link state unknown
1009 	 */
1010 	if (!mxfep->mxfe_resetting) {
1011 		mxfep->mxfe_linkup = LINK_STATE_UNKNOWN;
1012 		mxfep->mxfe_ifspeed = 0;
1013 		mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1014 		if (mxfep->mxfe_flags & MXFE_RUNNING)
1015 			mxfe_reportlink(mxfep);
1016 	}
1017 }
1018 
1019 /*
1020  * NWay support.
1021  */
1022 void
1023 mxfe_startnway(mxfe_t *mxfep)
1024 {
1025 	unsigned	nar;
1026 	unsigned	tctl;
1027 	unsigned	restart;
1028 
1029 	/* this should not happen in a healthy system */
1030 	if (mxfep->mxfe_linkstate != MXFE_NOLINK) {
1031 		DBG(DWARN, "link start called out of state (%x)",
1032 		    mxfep->mxfe_linkstate);
1033 		return;
1034 	}
1035 
1036 	if (mxfep->mxfe_adv_aneg == 0) {
1037 		/* not done for forced mode */
1038 		return;
1039 	}
1040 
1041 	nar = GETCSR(mxfep, CSR_NAR);
1042 	restart = nar & (NAR_TX_ENABLE | NAR_RX_ENABLE);
1043 	nar &= ~restart;
1044 
1045 	if (restart != 0)
1046 		mxfe_stopmac(mxfep);
1047 
1048 	nar |= NAR_SCR | NAR_PCS | NAR_HBD;
1049 	nar &= ~(NAR_FDX);
1050 
1051 	tctl = GETCSR(mxfep, CSR_TCTL);
1052 	tctl &= ~(TCTL_100FDX | TCTL_100HDX | TCTL_HDX);
1053 
1054 	if (mxfep->mxfe_adv_100fdx) {
1055 		tctl |= TCTL_100FDX;
1056 	}
1057 	if (mxfep->mxfe_adv_100hdx) {
1058 		tctl |= TCTL_100HDX;
1059 	}
1060 	if (mxfep->mxfe_adv_10fdx) {
1061 		nar |= NAR_FDX;
1062 	}
1063 	if (mxfep->mxfe_adv_10hdx) {
1064 		tctl |= TCTL_HDX;
1065 	}
1066 	tctl |= TCTL_PWR | TCTL_ANE | TCTL_LTE | TCTL_RSQ;
1067 
1068 	/* possibly we should add in support for PAUSE frames */
1069 	DBG(DPHY, "writing nar = 0x%x", nar);
1070 	PUTCSR(mxfep, CSR_NAR, nar);
1071 
1072 	DBG(DPHY, "writing tctl = 0x%x", tctl);
1073 	PUTCSR(mxfep, CSR_TCTL, tctl);
1074 
1075 	/* restart autonegotation */
1076 	DBG(DPHY, "writing tstat = 0x%x", TSTAT_ANS_START);
1077 	PUTCSR(mxfep, CSR_TSTAT, TSTAT_ANS_START);
1078 
1079 	/* restart tx/rx processes... */
1080 	if (restart != 0)
1081 		mxfe_startmac(mxfep);
1082 
1083 	/* Macronix initializations from Bolo Tsai */
1084 	PUTCSR(mxfep, CSR_MXMAGIC, 0x0b2c0000);
1085 	PUTCSR(mxfep, CSR_ACOMP, 0x11000);
1086 
1087 	mxfep->mxfe_linkstate = MXFE_NWAYCHECK;
1088 }
1089 
1090 void
1091 mxfe_checklinknway(mxfe_t *mxfep)
1092 {
1093 	unsigned	tstat, lpar;
1094 
1095 	DBG(DPHY, "NWay check, state %x", mxfep->mxfe_linkstate);
1096 	tstat = GETCSR(mxfep, CSR_TSTAT);
1097 	lpar = TSTAT_LPAR(tstat);
1098 
1099 	mxfep->mxfe_anlpar = lpar;
1100 	if (tstat & TSTAT_LPN) {
1101 		mxfep->mxfe_aner |= MII_AN_EXP_LPCANAN;
1102 	} else {
1103 		mxfep->mxfe_aner &= ~(MII_AN_EXP_LPCANAN);
1104 	}
1105 
1106 	DBG(DPHY, "tstat(CSR12) = 0x%x", tstat);
1107 	DBG(DPHY, "ANEG state = 0x%x", (tstat & TSTAT_ANS) >> 12);
1108 
1109 	if ((tstat & TSTAT_ANS) != TSTAT_ANS_OK) {
1110 		/* autoneg did not complete */
1111 		mxfep->mxfe_bmsr &= ~MII_STATUS_ANDONE;
1112 	} else {
1113 		mxfep->mxfe_bmsr |= ~MII_STATUS_ANDONE;
1114 	}
1115 
1116 	if ((tstat & TSTAT_100F) && (tstat & TSTAT_10F)) {
1117 		mxfep->mxfe_linkup = LINK_STATE_DOWN;
1118 		mxfep->mxfe_ifspeed = 0;
1119 		mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1120 		mxfep->mxfe_linkstate = MXFE_NOLINK;
1121 		mxfe_reportlink(mxfep);
1122 		mxfe_startnway(mxfep);
1123 		return;
1124 	}
1125 
1126 	/*
1127 	 * if the link is newly up, then we might need to set various
1128 	 * mode bits, or negotiate for parameters, etc.
1129 	 */
1130 	if (mxfep->mxfe_adv_aneg) {
1131 
1132 		uint16_t	anlpar;
1133 
1134 		mxfep->mxfe_linkup = LINK_STATE_UP;
1135 		anlpar = mxfep->mxfe_anlpar;
1136 
1137 		if (tstat & TSTAT_LPN) {
1138 			/* partner has NWay */
1139 
1140 			if ((anlpar & MII_ABILITY_100BASE_TX_FD) &&
1141 			    mxfep->mxfe_adv_100fdx) {
1142 				mxfep->mxfe_ifspeed = 100000000;
1143 				mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1144 			} else if ((anlpar & MII_ABILITY_100BASE_TX) &&
1145 			    mxfep->mxfe_adv_100hdx) {
1146 				mxfep->mxfe_ifspeed = 100000000;
1147 				mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1148 			} else if ((anlpar & MII_ABILITY_10BASE_T_FD) &&
1149 			    mxfep->mxfe_adv_10fdx) {
1150 				mxfep->mxfe_ifspeed = 10000000;
1151 				mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1152 			} else if ((anlpar & MII_ABILITY_10BASE_T) &&
1153 			    mxfep->mxfe_adv_10hdx) {
1154 				mxfep->mxfe_ifspeed = 10000000;
1155 				mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1156 			} else {
1157 				mxfep->mxfe_ifspeed = 0;
1158 			}
1159 		} else {
1160 			/* link partner does not have NWay */
1161 			/* just assume half duplex, since we can't detect */
1162 			mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1163 			if (!(tstat & TSTAT_100F)) {
1164 				DBG(DPHY, "Partner doesn't have NWAY");
1165 				mxfep->mxfe_ifspeed = 100000000;
1166 			} else {
1167 				mxfep->mxfe_ifspeed = 10000000;
1168 			}
1169 		}
1170 	} else {
1171 		/* forced modes */
1172 		mxfep->mxfe_linkup = LINK_STATE_UP;
1173 		if (mxfep->mxfe_adv_100fdx) {
1174 			mxfep->mxfe_ifspeed = 100000000;
1175 			mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1176 		} else if (mxfep->mxfe_adv_100hdx) {
1177 			mxfep->mxfe_ifspeed = 100000000;
1178 			mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1179 		} else if (mxfep->mxfe_adv_10fdx) {
1180 			mxfep->mxfe_ifspeed = 10000000;
1181 			mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1182 		} else if (mxfep->mxfe_adv_10hdx) {
1183 			mxfep->mxfe_ifspeed = 10000000;
1184 			mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1185 		} else {
1186 			mxfep->mxfe_ifspeed = 0;
1187 		}
1188 	}
1189 	mxfe_reportlink(mxfep);
1190 	mxfep->mxfe_linkstate = MXFE_GOODLINK;
1191 }
1192 
1193 void
1194 mxfe_startphynway(mxfe_t *mxfep)
1195 {
1196 	/* take NWay and PHY out of reset */
1197 	PUTCSR(mxfep, CSR_SIA, SIA_NRESET);
1198 	drv_usecwait(500);
1199 
1200 	mxfep->mxfe_linkstate = MXFE_NOLINK;
1201 	mxfep->mxfe_bmsr = MII_STATUS_CANAUTONEG |
1202 	    MII_STATUS_100_BASEX_FD | MII_STATUS_100_BASEX |
1203 	    MII_STATUS_10_FD | MII_STATUS_10;
1204 
1205 	/* lie about the transceiver... its not really 802.3u compliant */
1206 	mxfep->mxfe_phyaddr = 0;
1207 	mxfep->mxfe_phyinuse = XCVR_100X;
1208 	mxfep->mxfe_phyid = 0;
1209 
1210 	/* 100-T4 not supported with NWay */
1211 	mxfep->mxfe_adv_100T4 = 0;
1212 
1213 	/* make sure at least one valid mode is selected */
1214 	if ((!mxfep->mxfe_adv_100fdx) &&
1215 	    (!mxfep->mxfe_adv_100hdx) &&
1216 	    (!mxfep->mxfe_adv_10fdx) &&
1217 	    (!mxfep->mxfe_adv_10hdx)) {
1218 		mxfe_error(mxfep->mxfe_dip, "No valid link mode selected.");
1219 		mxfe_error(mxfep->mxfe_dip, "Powering down PHY.");
1220 		mxfe_stopphy(mxfep);
1221 		mxfep->mxfe_linkup = LINK_STATE_DOWN;
1222 		if (mxfep->mxfe_flags & MXFE_RUNNING)
1223 			mxfe_reportlink(mxfep);
1224 		return;
1225 	}
1226 
1227 	if (mxfep->mxfe_adv_aneg == 0) {
1228 		/* forced mode */
1229 		unsigned	nar;
1230 		unsigned	tctl;
1231 
1232 		nar = GETCSR(mxfep, CSR_NAR);
1233 		tctl = GETCSR(mxfep, CSR_TCTL);
1234 
1235 		ASSERT((nar & (NAR_TX_ENABLE | NAR_RX_ENABLE)) == 0);
1236 
1237 		nar &= ~(NAR_FDX | NAR_PORTSEL | NAR_SCR | NAR_SPEED);
1238 		tctl &= ~TCTL_ANE;
1239 		if (mxfep->mxfe_adv_100fdx) {
1240 			nar |= NAR_PORTSEL | NAR_PCS | NAR_SCR | NAR_FDX;
1241 		} else if (mxfep->mxfe_adv_100hdx) {
1242 			nar |= NAR_PORTSEL | NAR_PCS | NAR_SCR;
1243 		} else if (mxfep->mxfe_adv_10fdx) {
1244 			nar |= NAR_FDX | NAR_SPEED;
1245 		} else { /* mxfep->mxfe_adv_10hdx */
1246 			nar |= NAR_SPEED;
1247 		}
1248 
1249 		PUTCSR(mxfep, CSR_NAR, nar);
1250 		PUTCSR(mxfep, CSR_TCTL, tctl);
1251 
1252 		/* Macronix initializations from Bolo Tsai */
1253 		PUTCSR(mxfep, CSR_MXMAGIC, 0x0b2c0000);
1254 		PUTCSR(mxfep, CSR_ACOMP, 0x11000);
1255 	} else {
1256 		mxfe_startnway(mxfep);
1257 	}
1258 	PUTCSR(mxfep, CSR_TIMER, TIMER_LOOP |
1259 	    (MXFE_LINKTIMER * 1000 / TIMER_USEC));
1260 }
1261 
1262 /*
1263  * MII management.
1264  */
1265 void
1266 mxfe_startphymii(mxfe_t *mxfep)
1267 {
1268 	unsigned	phyaddr;
1269 	unsigned	bmcr;
1270 	unsigned	bmsr;
1271 	unsigned	anar;
1272 	unsigned	phyidr1;
1273 	unsigned	phyidr2;
1274 	int		retries;
1275 	int		cnt;
1276 
1277 	mxfep->mxfe_phyaddr = -1;
1278 
1279 	/* search for first PHY we can find */
1280 	for (phyaddr = 0; phyaddr < 32; phyaddr++) {
1281 		bmsr = mxfe_miiread(mxfep, phyaddr, MII_STATUS);
1282 		if ((bmsr != 0) && (bmsr != 0xffff)) {
1283 			mxfep->mxfe_phyaddr = phyaddr;
1284 			break;
1285 		}
1286 	}
1287 
1288 	phyidr1 = mxfe_miiread(mxfep, phyaddr, MII_PHYIDH);
1289 	phyidr2 = mxfe_miiread(mxfep, phyaddr, MII_PHYIDL);
1290 	mxfep->mxfe_phyid = (phyidr1 << 16) | (phyidr2);
1291 
1292 	/*
1293 	 * Generally, all Macronix based devices use an internal
1294 	 * 100BASE-TX internal transceiver.  If we ever run into a
1295 	 * variation on this, then the following logic will need to be
1296 	 * enhanced.
1297 	 *
1298 	 * One could question the value of the XCVR_INUSE field in the
1299 	 * MII statistics.
1300 	 */
1301 	if (bmsr & MII_STATUS_100_BASE_T4) {
1302 		mxfep->mxfe_phyinuse = XCVR_100T4;
1303 	} else {
1304 		mxfep->mxfe_phyinuse = XCVR_100X;
1305 	}
1306 
1307 	DBG(DPHY, "phy at %d: %x,%x", phyaddr, phyidr1, phyidr2);
1308 	DBG(DPHY, "bmsr = %x", mxfe_miiread(mxfep,
1309 	    mxfep->mxfe_phyaddr, MII_STATUS));
1310 	DBG(DPHY, "anar = %x", mxfe_miiread(mxfep,
1311 	    mxfep->mxfe_phyaddr, MII_AN_ADVERT));
1312 	DBG(DPHY, "anlpar = %x", mxfe_miiread(mxfep,
1313 	    mxfep->mxfe_phyaddr, MII_AN_LPABLE));
1314 	DBG(DPHY, "aner = %x", mxfe_miiread(mxfep,
1315 	    mxfep->mxfe_phyaddr, MII_AN_EXPANSION));
1316 
1317 	DBG(DPHY, "resetting phy");
1318 
1319 	/* we reset the phy block */
1320 	mxfe_miiwrite(mxfep, phyaddr, MII_CONTROL, MII_CONTROL_RESET);
1321 	/*
1322 	 * wait for it to complete -- 500usec is still to short to
1323 	 * bother getting the system clock involved.
1324 	 */
1325 	drv_usecwait(500);
1326 	for (retries = 0; retries < 10; retries++) {
1327 		if (mxfe_miiread(mxfep, phyaddr, MII_CONTROL) &
1328 		    MII_CONTROL_RESET) {
1329 			drv_usecwait(500);
1330 			continue;
1331 		}
1332 		break;
1333 	}
1334 	if (retries == 100) {
1335 		mxfe_error(mxfep->mxfe_dip, "timeout waiting on phy to reset");
1336 		return;
1337 	}
1338 
1339 	DBG(DPHY, "phy reset complete");
1340 
1341 	bmsr = mxfe_miiread(mxfep, phyaddr, MII_STATUS);
1342 	bmcr = mxfe_miiread(mxfep, phyaddr, MII_CONTROL);
1343 	anar = mxfe_miiread(mxfep, phyaddr, MII_AN_ADVERT);
1344 
1345 	anar &= ~(MII_ABILITY_100BASE_T4 |
1346 	    MII_ABILITY_100BASE_TX_FD | MII_ABILITY_100BASE_TX |
1347 	    MII_ABILITY_10BASE_T_FD | MII_ABILITY_10BASE_T);
1348 
1349 	/* disable modes not supported in hardware */
1350 	if (!(bmsr & MII_STATUS_100_BASE_T4)) {
1351 		mxfep->mxfe_adv_100T4 = 0;
1352 	}
1353 	if (!(bmsr & MII_STATUS_100_BASEX_FD)) {
1354 		mxfep->mxfe_adv_100fdx = 0;
1355 	}
1356 	if (!(bmsr & MII_STATUS_100_BASEX)) {
1357 		mxfep->mxfe_adv_100hdx = 0;
1358 	}
1359 	if (!(bmsr & MII_STATUS_10_FD)) {
1360 		mxfep->mxfe_adv_10fdx = 0;
1361 	}
1362 	if (!(bmsr & MII_STATUS_10)) {
1363 		mxfep->mxfe_adv_10hdx = 0;
1364 	}
1365 	if (!(bmsr & MII_STATUS_CANAUTONEG)) {
1366 		mxfep->mxfe_adv_aneg = 0;
1367 	}
1368 
1369 	cnt = 0;
1370 	if (mxfep->mxfe_adv_100T4) {
1371 		anar |= MII_ABILITY_100BASE_T4;
1372 		cnt++;
1373 	}
1374 	if (mxfep->mxfe_adv_100fdx) {
1375 		anar |= MII_ABILITY_100BASE_TX_FD;
1376 		cnt++;
1377 	}
1378 	if (mxfep->mxfe_adv_100hdx) {
1379 		anar |= MII_ABILITY_100BASE_TX;
1380 		cnt++;
1381 	}
1382 	if (mxfep->mxfe_adv_10fdx) {
1383 		anar |= MII_ABILITY_10BASE_T_FD;
1384 		cnt++;
1385 	}
1386 	if (mxfep->mxfe_adv_10hdx) {
1387 		anar |= MII_ABILITY_10BASE_T;
1388 		cnt++;
1389 	}
1390 
1391 	/*
1392 	 * Make certain at least one valid link mode is selected.
1393 	 */
1394 	if (!cnt) {
1395 		mxfe_error(mxfep->mxfe_dip, "No valid link mode selected.");
1396 		mxfe_error(mxfep->mxfe_dip, "Powering down PHY.");
1397 		mxfe_stopphy(mxfep);
1398 		mxfep->mxfe_linkup = LINK_STATE_DOWN;
1399 		if (mxfep->mxfe_flags & MXFE_RUNNING)
1400 			mxfe_reportlink(mxfep);
1401 		return;
1402 	}
1403 
1404 	if ((mxfep->mxfe_adv_aneg) && (bmsr & MII_STATUS_CANAUTONEG)) {
1405 		DBG(DPHY, "using autoneg mode");
1406 		bmcr = (MII_CONTROL_ANE | MII_CONTROL_RSAN);
1407 	} else {
1408 		DBG(DPHY, "using forced mode");
1409 		if (mxfep->mxfe_adv_100fdx) {
1410 			bmcr = (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX);
1411 		} else if (mxfep->mxfe_adv_100hdx) {
1412 			bmcr = MII_CONTROL_100MB;
1413 		} else if (mxfep->mxfe_adv_10fdx) {
1414 			bmcr = MII_CONTROL_FDUPLEX;
1415 		} else {
1416 			/* 10HDX */
1417 			bmcr = 0;
1418 		}
1419 	}
1420 
1421 	mxfep->mxfe_forcephy = 0;
1422 
1423 	DBG(DPHY, "programming anar to 0x%x", anar);
1424 	mxfe_miiwrite(mxfep, phyaddr, MII_AN_ADVERT, anar);
1425 	DBG(DPHY, "programming bmcr to 0x%x", bmcr);
1426 	mxfe_miiwrite(mxfep, phyaddr, MII_CONTROL, bmcr);
1427 
1428 	/*
1429 	 * schedule a query of the link status
1430 	 */
1431 	PUTCSR(mxfep, CSR_TIMER, TIMER_LOOP |
1432 	    (MXFE_LINKTIMER * 1000 / TIMER_USEC));
1433 }
1434 
1435 void
1436 mxfe_reportlink(mxfe_t *mxfep)
1437 {
1438 	int changed = 0;
1439 
1440 	if (mxfep->mxfe_ifspeed != mxfep->mxfe_lastifspeed) {
1441 		mxfep->mxfe_lastifspeed = mxfep->mxfe_ifspeed;
1442 		changed++;
1443 	}
1444 	if (mxfep->mxfe_duplex != mxfep->mxfe_lastduplex) {
1445 		mxfep->mxfe_lastduplex = mxfep->mxfe_duplex;
1446 		changed++;
1447 	}
1448 	if (mxfep->mxfe_linkup != mxfep->mxfe_lastlinkup) {
1449 		mxfep->mxfe_lastlinkup = mxfep->mxfe_linkup;
1450 		changed++;
1451 	}
1452 	if (changed)
1453 		mac_link_update(mxfep->mxfe_mh, mxfep->mxfe_linkup);
1454 }
1455 
1456 void
1457 mxfe_checklink(mxfe_t *mxfep)
1458 {
1459 	if ((mxfep->mxfe_flags & MXFE_RUNNING) == 0)
1460 		return;
1461 
1462 	if ((mxfep->mxfe_txstall_time != 0) &&
1463 	    (gethrtime() > mxfep->mxfe_txstall_time) &&
1464 	    (mxfep->mxfe_txavail != MXFE_TXRING)) {
1465 		mxfep->mxfe_txstall_time = 0;
1466 		mxfe_error(mxfep->mxfe_dip, "TX stall detected!");
1467 		mxfe_resetall(mxfep);
1468 		return;
1469 	}
1470 
1471 	switch (MXFE_MODEL(mxfep)) {
1472 	case MXFE_98713A:
1473 		mxfe_checklinkmii(mxfep);
1474 		break;
1475 	default:
1476 		mxfe_checklinknway(mxfep);
1477 	}
1478 }
1479 
1480 void
1481 mxfe_checklinkmii(mxfe_t *mxfep)
1482 {
1483 	/* read MII state registers */
1484 	uint16_t 	bmsr;
1485 	uint16_t 	bmcr;
1486 	uint16_t 	anar;
1487 	uint16_t 	anlpar;
1488 	uint16_t 	aner;
1489 
1490 	/* read this twice, to clear latched link state */
1491 	bmsr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_STATUS);
1492 	bmsr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_STATUS);
1493 	bmcr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_CONTROL);
1494 	anar = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_ADVERT);
1495 	anlpar = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_LPABLE);
1496 	aner = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_EXPANSION);
1497 
1498 	mxfep->mxfe_bmsr = bmsr;
1499 	mxfep->mxfe_anlpar = anlpar;
1500 	mxfep->mxfe_aner = aner;
1501 
1502 	if (bmsr & MII_STATUS_REMFAULT) {
1503 		mxfe_error(mxfep->mxfe_dip, "Remote fault detected.");
1504 	}
1505 	if (bmsr & MII_STATUS_JABBERING) {
1506 		mxfe_error(mxfep->mxfe_dip, "Jabber condition detected.");
1507 	}
1508 	if ((bmsr & MII_STATUS_LINKUP) == 0) {
1509 		/* no link */
1510 		mxfep->mxfe_ifspeed = 0;
1511 		mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1512 		mxfep->mxfe_linkup = LINK_STATE_DOWN;
1513 		mxfe_reportlink(mxfep);
1514 		return;
1515 	}
1516 
1517 	DBG(DCHATTY, "link up!");
1518 	mxfep->mxfe_linkup = LINK_STATE_UP;
1519 
1520 	if (!(bmcr & MII_CONTROL_ANE)) {
1521 		/* forced mode */
1522 		if (bmcr & MII_CONTROL_100MB) {
1523 			mxfep->mxfe_ifspeed = 100000000;
1524 		} else {
1525 			mxfep->mxfe_ifspeed = 10000000;
1526 		}
1527 		if (bmcr & MII_CONTROL_FDUPLEX) {
1528 			mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1529 		} else {
1530 			mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1531 		}
1532 	} else if ((!(bmsr & MII_STATUS_CANAUTONEG)) ||
1533 	    (!(bmsr & MII_STATUS_ANDONE))) {
1534 		mxfep->mxfe_ifspeed = 0;
1535 		mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1536 	} else if (anar & anlpar & MII_ABILITY_100BASE_TX_FD) {
1537 		mxfep->mxfe_ifspeed = 100000000;
1538 		mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1539 	} else if (anar & anlpar & MII_ABILITY_100BASE_T4) {
1540 		mxfep->mxfe_ifspeed = 100000000;
1541 		mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1542 	} else if (anar & anlpar & MII_ABILITY_100BASE_TX) {
1543 		mxfep->mxfe_ifspeed = 100000000;
1544 		mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1545 	} else if (anar & anlpar & MII_ABILITY_10BASE_T_FD) {
1546 		mxfep->mxfe_ifspeed = 10000000;
1547 		mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1548 	} else if (anar & anlpar & MII_ABILITY_10BASE_T) {
1549 		mxfep->mxfe_ifspeed = 10000000;
1550 		mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1551 	} else {
1552 		mxfep->mxfe_ifspeed = 0;
1553 		mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1554 	}
1555 
1556 	mxfe_reportlink(mxfep);
1557 }
1558 
1559 void
1560 mxfe_miitristate(mxfe_t *mxfep)
1561 {
1562 	unsigned val = SPR_SROM_WRITE | SPR_MII_CTRL;
1563 	PUTCSR(mxfep, CSR_SPR, val);
1564 	drv_usecwait(1);
1565 	PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1566 	drv_usecwait(1);
1567 }
1568 
1569 void
1570 mxfe_miiwritebit(mxfe_t *mxfep, int bit)
1571 {
1572 	unsigned val = bit ? SPR_MII_DOUT : 0;
1573 	PUTCSR(mxfep, CSR_SPR, val);
1574 	drv_usecwait(1);
1575 	PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1576 	drv_usecwait(1);
1577 }
1578 
1579 int
1580 mxfe_miireadbit(mxfe_t *mxfep)
1581 {
1582 	unsigned val = SPR_MII_CTRL | SPR_SROM_READ;
1583 	int bit;
1584 	PUTCSR(mxfep, CSR_SPR, val);
1585 	drv_usecwait(1);
1586 	bit = (GETCSR(mxfep, CSR_SPR) & SPR_MII_DIN) ? 1 : 0;
1587 	PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1588 	drv_usecwait(1);
1589 	return (bit);
1590 }
1591 
1592 unsigned
1593 mxfe_miiread(mxfe_t *mxfep, int phy, int reg)
1594 {
1595 	switch (MXFE_MODEL(mxfep)) {
1596 	case MXFE_98713A:
1597 		return (mxfe_miiread98713(mxfep, phy, reg));
1598 	default:
1599 		return (0xffff);
1600 	}
1601 }
1602 
1603 unsigned
1604 mxfe_miireadgeneral(mxfe_t *mxfep, int phy, int reg)
1605 {
1606 	unsigned	value = 0;
1607 	int		i;
1608 
1609 	/* send the 32 bit preamble */
1610 	for (i = 0; i < 32; i++) {
1611 		mxfe_miiwritebit(mxfep, 1);
1612 	}
1613 
1614 	/* send the start code - 01b */
1615 	mxfe_miiwritebit(mxfep, 0);
1616 	mxfe_miiwritebit(mxfep, 1);
1617 
1618 	/* send the opcode for read, - 10b */
1619 	mxfe_miiwritebit(mxfep, 1);
1620 	mxfe_miiwritebit(mxfep, 0);
1621 
1622 	/* next we send the 5 bit phy address */
1623 	for (i = 0x10; i > 0; i >>= 1) {
1624 		mxfe_miiwritebit(mxfep, (phy & i) ? 1 : 0);
1625 	}
1626 
1627 	/* the 5 bit register address goes next */
1628 	for (i = 0x10; i > 0; i >>= 1) {
1629 		mxfe_miiwritebit(mxfep, (reg & i) ? 1 : 0);
1630 	}
1631 
1632 	/* turnaround - tristate followed by logic 0 */
1633 	mxfe_miitristate(mxfep);
1634 	mxfe_miiwritebit(mxfep, 0);
1635 
1636 	/* read the 16 bit register value */
1637 	for (i = 0x8000; i > 0; i >>= 1) {
1638 		value <<= 1;
1639 		value |= mxfe_miireadbit(mxfep);
1640 	}
1641 	mxfe_miitristate(mxfep);
1642 	return (value);
1643 }
1644 
1645 unsigned
1646 mxfe_miiread98713(mxfe_t *mxfep, int phy, int reg)
1647 {
1648 	unsigned nar;
1649 	unsigned retval;
1650 	/*
1651 	 * like an ordinary MII, but we have to turn off portsel while
1652 	 * we read it.
1653 	 */
1654 	nar = GETCSR(mxfep, CSR_NAR);
1655 	PUTCSR(mxfep, CSR_NAR, nar & ~NAR_PORTSEL);
1656 	retval = mxfe_miireadgeneral(mxfep, phy, reg);
1657 	PUTCSR(mxfep, CSR_NAR, nar);
1658 	return (retval);
1659 }
1660 
1661 void
1662 mxfe_miiwrite(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1663 {
1664 	switch (MXFE_MODEL(mxfep)) {
1665 	case MXFE_98713A:
1666 		mxfe_miiwrite98713(mxfep, phy, reg, val);
1667 		break;
1668 	default:
1669 		break;
1670 	}
1671 }
1672 
1673 void
1674 mxfe_miiwritegeneral(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1675 {
1676 	int i;
1677 
1678 	/* send the 32 bit preamble */
1679 	for (i = 0; i < 32; i++) {
1680 		mxfe_miiwritebit(mxfep, 1);
1681 	}
1682 
1683 	/* send the start code - 01b */
1684 	mxfe_miiwritebit(mxfep, 0);
1685 	mxfe_miiwritebit(mxfep, 1);
1686 
1687 	/* send the opcode for write, - 01b */
1688 	mxfe_miiwritebit(mxfep, 0);
1689 	mxfe_miiwritebit(mxfep, 1);
1690 
1691 	/* next we send the 5 bit phy address */
1692 	for (i = 0x10; i > 0; i >>= 1) {
1693 		mxfe_miiwritebit(mxfep, (phy & i) ? 1 : 0);
1694 	}
1695 
1696 	/* the 5 bit register address goes next */
1697 	for (i = 0x10; i > 0; i >>= 1) {
1698 		mxfe_miiwritebit(mxfep, (reg & i) ? 1 : 0);
1699 	}
1700 
1701 	/* turnaround - tristate followed by logic 0 */
1702 	mxfe_miitristate(mxfep);
1703 	mxfe_miiwritebit(mxfep, 0);
1704 
1705 	/* now write out our data (16 bits) */
1706 	for (i = 0x8000; i > 0; i >>= 1) {
1707 		mxfe_miiwritebit(mxfep, (val & i) ? 1 : 0);
1708 	}
1709 
1710 	/* idle mode */
1711 	mxfe_miitristate(mxfep);
1712 }
1713 
1714 void
1715 mxfe_miiwrite98713(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1716 {
1717 	unsigned nar;
1718 	/*
1719 	 * like an ordinary MII, but we have to turn off portsel while
1720 	 * we read it.
1721 	 */
1722 	nar = GETCSR(mxfep, CSR_NAR);
1723 	PUTCSR(mxfep, CSR_NAR, nar & ~NAR_PORTSEL);
1724 	mxfe_miiwritegeneral(mxfep, phy, reg, val);
1725 	PUTCSR(mxfep, CSR_NAR, nar);
1726 }
1727 
1728 int
1729 mxfe_m_start(void *arg)
1730 {
1731 	mxfe_t	*mxfep = arg;
1732 
1733 	/* grab exclusive access to the card */
1734 	mutex_enter(&mxfep->mxfe_intrlock);
1735 	mutex_enter(&mxfep->mxfe_xmtlock);
1736 
1737 	mxfe_startall(mxfep);
1738 	mxfep->mxfe_flags |= MXFE_RUNNING;
1739 
1740 	mutex_exit(&mxfep->mxfe_xmtlock);
1741 	mutex_exit(&mxfep->mxfe_intrlock);
1742 	return (0);
1743 }
1744 
1745 void
1746 mxfe_m_stop(void *arg)
1747 {
1748 	mxfe_t	*mxfep = arg;
1749 
1750 	/* exclusive access to the hardware! */
1751 	mutex_enter(&mxfep->mxfe_intrlock);
1752 	mutex_enter(&mxfep->mxfe_xmtlock);
1753 
1754 	mxfe_stopall(mxfep);
1755 	mxfep->mxfe_flags &= ~MXFE_RUNNING;
1756 
1757 	mutex_exit(&mxfep->mxfe_xmtlock);
1758 	mutex_exit(&mxfep->mxfe_intrlock);
1759 }
1760 
1761 void
1762 mxfe_startmac(mxfe_t *mxfep)
1763 {
1764 	/* verify exclusive access to the card */
1765 	ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1766 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1767 
1768 	/* start the card */
1769 	SETBIT(mxfep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1770 
1771 	if (mxfep->mxfe_txavail != MXFE_TXRING)
1772 		PUTCSR(mxfep, CSR_TDR, 0);
1773 
1774 	/* tell the mac that we are ready to go! */
1775 	if (mxfep->mxfe_flags & MXFE_RUNNING)
1776 		mac_tx_update(mxfep->mxfe_mh);
1777 }
1778 
1779 void
1780 mxfe_stopmac(mxfe_t *mxfep)
1781 {
1782 	int		i;
1783 
1784 	/* exclusive access to the hardware! */
1785 	ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1786 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1787 
1788 	CLRBIT(mxfep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1789 
1790 	/*
1791 	 * A 1518 byte frame at 10Mbps takes about 1.2 msec to drain.
1792 	 * We just add up to the nearest msec (2), which should be
1793 	 * plenty to complete.
1794 	 *
1795 	 * Note that some chips never seem to indicate the transition to
1796 	 * the stopped state properly.  Experience shows that we can safely
1797 	 * proceed anyway, after waiting the requisite timeout.
1798 	 */
1799 	for (i = 2000; i != 0; i -= 10) {
1800 		if ((GETCSR(mxfep, CSR_SR) & (SR_TX_STATE | SR_RX_STATE)) == 0)
1801 			break;
1802 		drv_usecwait(10);
1803 	}
1804 
1805 	/* prevent an interrupt */
1806 	PUTCSR(mxfep, CSR_SR, INT_RXSTOPPED | INT_TXSTOPPED);
1807 }
1808 
1809 void
1810 mxfe_resetrings(mxfe_t *mxfep)
1811 {
1812 	int	i;
1813 
1814 	/* now we need to reset the pointers... */
1815 	PUTCSR(mxfep, CSR_RDB, 0);
1816 	PUTCSR(mxfep, CSR_TDB, 0);
1817 
1818 	/* reset the descriptor ring pointers */
1819 	mxfep->mxfe_rxhead = 0;
1820 	mxfep->mxfe_txreclaim = 0;
1821 	mxfep->mxfe_txsend = 0;
1822 	mxfep->mxfe_txavail = MXFE_TXRING;
1823 
1824 	/* set up transmit descriptor ring */
1825 	for (i = 0; i < MXFE_TXRING; i++) {
1826 		mxfe_desc_t	*tmdp = &mxfep->mxfe_txdescp[i];
1827 		unsigned	control = 0;
1828 		if (i == (MXFE_TXRING - 1)) {
1829 			control |= TXCTL_ENDRING;
1830 		}
1831 		PUTTXDESC(mxfep, tmdp->desc_status, 0);
1832 		PUTTXDESC(mxfep, tmdp->desc_control, control);
1833 		PUTTXDESC(mxfep, tmdp->desc_buffer1, 0);
1834 		PUTTXDESC(mxfep, tmdp->desc_buffer2, 0);
1835 		SYNCTXDESC(mxfep, i, DDI_DMA_SYNC_FORDEV);
1836 	}
1837 	PUTCSR(mxfep, CSR_TDB, mxfep->mxfe_txdesc_paddr);
1838 
1839 	/* make the receive buffers available */
1840 	for (i = 0; i < MXFE_RXRING; i++) {
1841 		mxfe_rxbuf_t	*rxb = mxfep->mxfe_rxbufs[i];
1842 		mxfe_desc_t	*rmdp = &mxfep->mxfe_rxdescp[i];
1843 		unsigned	control;
1844 
1845 		control = MXFE_BUFSZ & RXCTL_BUFLEN1;
1846 		if (i == (MXFE_RXRING - 1)) {
1847 			control |= RXCTL_ENDRING;
1848 		}
1849 		PUTRXDESC(mxfep, rmdp->desc_buffer1, rxb->rxb_paddr);
1850 		PUTRXDESC(mxfep, rmdp->desc_buffer2, 0);
1851 		PUTRXDESC(mxfep, rmdp->desc_control, control);
1852 		PUTRXDESC(mxfep, rmdp->desc_status, RXSTAT_OWN);
1853 		SYNCRXDESC(mxfep, i, DDI_DMA_SYNC_FORDEV);
1854 	}
1855 	PUTCSR(mxfep, CSR_RDB, mxfep->mxfe_rxdesc_paddr);
1856 }
1857 
1858 void
1859 mxfe_stopall(mxfe_t *mxfep)
1860 {
1861 	mxfe_disableinterrupts(mxfep);
1862 
1863 	mxfe_stopmac(mxfep);
1864 
1865 	/* stop the phy */
1866 	mxfe_stopphy(mxfep);
1867 }
1868 
1869 void
1870 mxfe_startall(mxfe_t *mxfep)
1871 {
1872 	ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1873 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1874 
1875 	/* make sure interrupts are disabled to begin */
1876 	mxfe_disableinterrupts(mxfep);
1877 
1878 	/* initialize the chip */
1879 	(void) mxfe_initialize(mxfep);
1880 
1881 	/* now we can enable interrupts */
1882 	mxfe_enableinterrupts(mxfep);
1883 
1884 	/* start up the phy */
1885 	mxfe_startphy(mxfep);
1886 
1887 	/* start up the mac */
1888 	mxfe_startmac(mxfep);
1889 }
1890 
1891 void
1892 mxfe_resetall(mxfe_t *mxfep)
1893 {
1894 	mxfep->mxfe_resetting = B_TRUE;
1895 	mxfe_stopall(mxfep);
1896 	mxfep->mxfe_resetting = B_FALSE;
1897 	mxfe_startall(mxfep);
1898 }
1899 
1900 mxfe_txbuf_t *
1901 mxfe_alloctxbuf(mxfe_t *mxfep)
1902 {
1903 	ddi_dma_cookie_t	dmac;
1904 	unsigned		ncookies;
1905 	mxfe_txbuf_t		*txb;
1906 	size_t			len;
1907 
1908 	txb = kmem_zalloc(sizeof (*txb), KM_SLEEP);
1909 
1910 	if (ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_txattr,
1911 	    DDI_DMA_SLEEP, NULL, &txb->txb_dmah) != DDI_SUCCESS) {
1912 		return (NULL);
1913 	}
1914 
1915 	if (ddi_dma_mem_alloc(txb->txb_dmah, MXFE_BUFSZ, &mxfe_bufattr,
1916 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &txb->txb_buf,
1917 	    &len, &txb->txb_acch) != DDI_SUCCESS) {
1918 		return (NULL);
1919 	}
1920 	if (ddi_dma_addr_bind_handle(txb->txb_dmah, NULL, txb->txb_buf,
1921 	    len, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1922 	    &dmac, &ncookies) != DDI_DMA_MAPPED) {
1923 		return (NULL);
1924 	}
1925 	txb->txb_paddr = dmac.dmac_address;
1926 
1927 	return (txb);
1928 }
1929 
1930 void
1931 mxfe_destroytxbuf(mxfe_txbuf_t *txb)
1932 {
1933 	if (txb != NULL) {
1934 		if (txb->txb_paddr)
1935 			(void) ddi_dma_unbind_handle(txb->txb_dmah);
1936 		if (txb->txb_acch)
1937 			ddi_dma_mem_free(&txb->txb_acch);
1938 		if (txb->txb_dmah)
1939 			ddi_dma_free_handle(&txb->txb_dmah);
1940 		kmem_free(txb, sizeof (*txb));
1941 	}
1942 }
1943 
1944 mxfe_rxbuf_t *
1945 mxfe_allocrxbuf(mxfe_t *mxfep)
1946 {
1947 	mxfe_rxbuf_t 		*rxb;
1948 	size_t			len;
1949 	unsigned		ccnt;
1950 	ddi_dma_cookie_t	dmac;
1951 
1952 	rxb = kmem_zalloc(sizeof (*rxb), KM_SLEEP);
1953 
1954 	if (ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
1955 	    DDI_DMA_SLEEP, NULL, &rxb->rxb_dmah) != DDI_SUCCESS) {
1956 		kmem_free(rxb, sizeof (*rxb));
1957 		return (NULL);
1958 	}
1959 	if (ddi_dma_mem_alloc(rxb->rxb_dmah, MXFE_BUFSZ, &mxfe_bufattr,
1960 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1961 	    &rxb->rxb_buf, &len, &rxb->rxb_acch) != DDI_SUCCESS) {
1962 		ddi_dma_free_handle(&rxb->rxb_dmah);
1963 		kmem_free(rxb, sizeof (*rxb));
1964 		return (NULL);
1965 	}
1966 	if (ddi_dma_addr_bind_handle(rxb->rxb_dmah, NULL, rxb->rxb_buf, len,
1967 	    DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dmac,
1968 	    &ccnt) != DDI_DMA_MAPPED) {
1969 		ddi_dma_mem_free(&rxb->rxb_acch);
1970 		ddi_dma_free_handle(&rxb->rxb_dmah);
1971 		kmem_free(rxb, sizeof (*rxb));
1972 		return (NULL);
1973 	}
1974 	rxb->rxb_paddr = dmac.dmac_address;
1975 
1976 	return (rxb);
1977 }
1978 
1979 void
1980 mxfe_destroyrxbuf(mxfe_rxbuf_t *rxb)
1981 {
1982 	if (rxb != NULL) {
1983 		(void) ddi_dma_unbind_handle(rxb->rxb_dmah);
1984 		ddi_dma_mem_free(&rxb->rxb_acch);
1985 		ddi_dma_free_handle(&rxb->rxb_dmah);
1986 		kmem_free(rxb, sizeof (*rxb));
1987 	}
1988 }
1989 
1990 /*
1991  * Allocate receive resources.
1992  */
1993 int
1994 mxfe_allocrxring(mxfe_t *mxfep)
1995 {
1996 	int			rval;
1997 	int			i;
1998 	size_t			size;
1999 	size_t			len;
2000 	ddi_dma_cookie_t	dmac;
2001 	unsigned		ncookies;
2002 	caddr_t			kaddr;
2003 
2004 	size = MXFE_RXRING * sizeof (mxfe_desc_t);
2005 
2006 	rval = ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
2007 	    DDI_DMA_SLEEP, NULL, &mxfep->mxfe_rxdesc_dmah);
2008 	if (rval != DDI_SUCCESS) {
2009 		mxfe_error(mxfep->mxfe_dip,
2010 		    "unable to allocate DMA handle for rx descriptors");
2011 		return (DDI_FAILURE);
2012 	}
2013 
2014 	rval = ddi_dma_mem_alloc(mxfep->mxfe_rxdesc_dmah, size, &mxfe_devattr,
2015 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
2016 	    &mxfep->mxfe_rxdesc_acch);
2017 	if (rval != DDI_SUCCESS) {
2018 		mxfe_error(mxfep->mxfe_dip,
2019 		    "unable to allocate DMA memory for rx descriptors");
2020 		return (DDI_FAILURE);
2021 	}
2022 
2023 	rval = ddi_dma_addr_bind_handle(mxfep->mxfe_rxdesc_dmah, NULL, kaddr,
2024 	    size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
2025 	    &dmac, &ncookies);
2026 	if (rval != DDI_DMA_MAPPED) {
2027 		mxfe_error(mxfep->mxfe_dip,
2028 		    "unable to bind DMA for rx descriptors");
2029 		return (DDI_FAILURE);
2030 	}
2031 
2032 	/* because of mxfe_dma_attr */
2033 	ASSERT(ncookies == 1);
2034 
2035 	/* we take the 32-bit physical address out of the cookie */
2036 	mxfep->mxfe_rxdesc_paddr = dmac.dmac_address;
2037 	mxfep->mxfe_rxdescp = (void *)kaddr;
2038 
2039 	/* allocate buffer pointers (not the buffers themselves, yet) */
2040 	mxfep->mxfe_rxbufs = kmem_zalloc(MXFE_RXRING * sizeof (mxfe_rxbuf_t *),
2041 	    KM_SLEEP);
2042 
2043 	/* now allocate rx buffers */
2044 	for (i = 0; i < MXFE_RXRING; i++) {
2045 		mxfe_rxbuf_t *rxb = mxfe_allocrxbuf(mxfep);
2046 		if (rxb == NULL)
2047 			return (DDI_FAILURE);
2048 		mxfep->mxfe_rxbufs[i] = rxb;
2049 	}
2050 
2051 	return (DDI_SUCCESS);
2052 }
2053 
2054 /*
2055  * Allocate transmit resources.
2056  */
2057 int
2058 mxfe_alloctxring(mxfe_t *mxfep)
2059 {
2060 	int			rval;
2061 	int			i;
2062 	size_t			size;
2063 	size_t			len;
2064 	ddi_dma_cookie_t	dmac;
2065 	unsigned		ncookies;
2066 	caddr_t			kaddr;
2067 
2068 	size = MXFE_TXRING * sizeof (mxfe_desc_t);
2069 
2070 	rval = ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
2071 	    DDI_DMA_SLEEP, NULL, &mxfep->mxfe_txdesc_dmah);
2072 	if (rval != DDI_SUCCESS) {
2073 		mxfe_error(mxfep->mxfe_dip,
2074 		    "unable to allocate DMA handle for tx descriptors");
2075 		return (DDI_FAILURE);
2076 	}
2077 
2078 	rval = ddi_dma_mem_alloc(mxfep->mxfe_txdesc_dmah, size, &mxfe_devattr,
2079 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
2080 	    &mxfep->mxfe_txdesc_acch);
2081 	if (rval != DDI_SUCCESS) {
2082 		mxfe_error(mxfep->mxfe_dip,
2083 		    "unable to allocate DMA memory for tx descriptors");
2084 		return (DDI_FAILURE);
2085 	}
2086 
2087 	rval = ddi_dma_addr_bind_handle(mxfep->mxfe_txdesc_dmah, NULL, kaddr,
2088 	    size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
2089 	    &dmac, &ncookies);
2090 	if (rval != DDI_DMA_MAPPED) {
2091 		mxfe_error(mxfep->mxfe_dip,
2092 		    "unable to bind DMA for tx descriptors");
2093 		return (DDI_FAILURE);
2094 	}
2095 
2096 	/* because of mxfe_dma_attr */
2097 	ASSERT(ncookies == 1);
2098 
2099 	/* we take the 32-bit physical address out of the cookie */
2100 	mxfep->mxfe_txdesc_paddr = dmac.dmac_address;
2101 	mxfep->mxfe_txdescp = (void *)kaddr;
2102 
2103 	/* allocate buffer pointers (not the buffers themselves, yet) */
2104 	mxfep->mxfe_txbufs = kmem_zalloc(MXFE_TXRING * sizeof (mxfe_txbuf_t *),
2105 	    KM_SLEEP);
2106 
2107 	/* now allocate tx buffers */
2108 	for (i = 0; i < MXFE_TXRING; i++) {
2109 		mxfe_txbuf_t *txb = mxfe_alloctxbuf(mxfep);
2110 		if (txb == NULL)
2111 			return (DDI_FAILURE);
2112 		/* stick it in the stack */
2113 		mxfep->mxfe_txbufs[i] = txb;
2114 	}
2115 
2116 	return (DDI_SUCCESS);
2117 }
2118 
2119 void
2120 mxfe_freerxring(mxfe_t *mxfep)
2121 {
2122 	int		i;
2123 
2124 	for (i = 0; i < MXFE_RXRING; i++) {
2125 		mxfe_destroyrxbuf(mxfep->mxfe_rxbufs[i]);
2126 	}
2127 
2128 	if (mxfep->mxfe_rxbufs) {
2129 		kmem_free(mxfep->mxfe_rxbufs,
2130 		    MXFE_RXRING * sizeof (mxfe_rxbuf_t *));
2131 	}
2132 
2133 	if (mxfep->mxfe_rxdesc_paddr)
2134 		(void) ddi_dma_unbind_handle(mxfep->mxfe_rxdesc_dmah);
2135 	if (mxfep->mxfe_rxdesc_acch)
2136 		ddi_dma_mem_free(&mxfep->mxfe_rxdesc_acch);
2137 	if (mxfep->mxfe_rxdesc_dmah)
2138 		ddi_dma_free_handle(&mxfep->mxfe_rxdesc_dmah);
2139 }
2140 
2141 void
2142 mxfe_freetxring(mxfe_t *mxfep)
2143 {
2144 	int			i;
2145 
2146 	for (i = 0; i < MXFE_TXRING; i++) {
2147 		mxfe_destroytxbuf(mxfep->mxfe_txbufs[i]);
2148 	}
2149 
2150 	if (mxfep->mxfe_txbufs) {
2151 		kmem_free(mxfep->mxfe_txbufs,
2152 		    MXFE_TXRING * sizeof (mxfe_txbuf_t *));
2153 	}
2154 	if (mxfep->mxfe_txdesc_paddr)
2155 		(void) ddi_dma_unbind_handle(mxfep->mxfe_txdesc_dmah);
2156 	if (mxfep->mxfe_txdesc_acch)
2157 		ddi_dma_mem_free(&mxfep->mxfe_txdesc_acch);
2158 	if (mxfep->mxfe_txdesc_dmah)
2159 		ddi_dma_free_handle(&mxfep->mxfe_txdesc_dmah);
2160 }
2161 
2162 /*
2163  * Interrupt service routine.
2164  */
2165 unsigned
2166 mxfe_intr(caddr_t arg)
2167 {
2168 	mxfe_t		*mxfep = (void *)arg;
2169 	uint32_t	status;
2170 	mblk_t		*mp = NULL;
2171 
2172 	mutex_enter(&mxfep->mxfe_intrlock);
2173 
2174 	if (mxfep->mxfe_flags & MXFE_SUSPENDED) {
2175 		/* we cannot receive interrupts! */
2176 		mutex_exit(&mxfep->mxfe_intrlock);
2177 		return (DDI_INTR_UNCLAIMED);
2178 	}
2179 
2180 	/* check interrupt status bits, did we interrupt? */
2181 	status = GETCSR(mxfep, CSR_SR) & INT_ALL;
2182 
2183 	if (status == 0) {
2184 		KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
2185 		mutex_exit(&mxfep->mxfe_intrlock);
2186 		return (DDI_INTR_UNCLAIMED);
2187 	}
2188 	/* ack the interrupt */
2189 	PUTCSR(mxfep, CSR_SR, status);
2190 	KIOIP->intrs[KSTAT_INTR_HARD]++;
2191 
2192 	if (!(mxfep->mxfe_flags & MXFE_RUNNING)) {
2193 		/* not running, don't touch anything */
2194 		mutex_exit(&mxfep->mxfe_intrlock);
2195 		return (DDI_INTR_CLAIMED);
2196 	}
2197 
2198 	if (status & INT_RXOK) {
2199 		/* receive packets */
2200 		mp = mxfe_receive(mxfep);
2201 	}
2202 
2203 	if (status & INT_TXOK) {
2204 		/* transmit completed */
2205 		mutex_enter(&mxfep->mxfe_xmtlock);
2206 		mxfe_reclaim(mxfep);
2207 		mutex_exit(&mxfep->mxfe_xmtlock);
2208 	}
2209 
2210 	if (((status & (INT_TIMER|INT_ANEG)) != 0) ||
2211 	    ((mxfep->mxfe_linkup == LINK_STATE_UP) &&
2212 	    ((status & (INT_10LINK|INT_100LINK)) != 0))) {
2213 		/* rescan the link */
2214 		mutex_enter(&mxfep->mxfe_xmtlock);
2215 		mxfe_checklink(mxfep);
2216 		mutex_exit(&mxfep->mxfe_xmtlock);
2217 	}
2218 
2219 	if (status & (INT_RXSTOPPED|INT_TXSTOPPED|INT_RXNOBUF|
2220 	    INT_RXJABBER|INT_TXJABBER|INT_TXUNDERFLOW)) {
2221 
2222 		if (status & (INT_RXJABBER | INT_TXJABBER)) {
2223 			mxfep->mxfe_jabber++;
2224 		}
2225 		DBG(DWARN, "resetting mac, status %x", status);
2226 		mutex_enter(&mxfep->mxfe_xmtlock);
2227 		mxfe_resetall(mxfep);
2228 		mutex_exit(&mxfep->mxfe_xmtlock);
2229 	}
2230 
2231 	if (status & INT_BUSERR) {
2232 		switch (status & SR_BERR_TYPE) {
2233 		case SR_BERR_PARITY:
2234 			mxfe_error(mxfep->mxfe_dip, "PCI parity error");
2235 			break;
2236 		case SR_BERR_TARGET_ABORT:
2237 			mxfe_error(mxfep->mxfe_dip, "PCI target abort");
2238 			break;
2239 		case SR_BERR_MASTER_ABORT:
2240 			mxfe_error(mxfep->mxfe_dip, "PCI master abort");
2241 			break;
2242 		default:
2243 			mxfe_error(mxfep->mxfe_dip, "Unknown PCI error");
2244 			break;
2245 		}
2246 
2247 		/* reset the chip in an attempt to fix things */
2248 		mutex_enter(&mxfep->mxfe_xmtlock);
2249 		mxfe_resetall(mxfep);
2250 		mutex_exit(&mxfep->mxfe_xmtlock);
2251 	}
2252 
2253 	mutex_exit(&mxfep->mxfe_intrlock);
2254 
2255 	/*
2256 	 * Send up packets.  We do this outside of the intrlock.
2257 	 */
2258 	if (mp) {
2259 		mac_rx(mxfep->mxfe_mh, NULL, mp);
2260 	}
2261 
2262 	return (DDI_INTR_CLAIMED);
2263 }
2264 
2265 void
2266 mxfe_enableinterrupts(mxfe_t *mxfep)
2267 {
2268 	unsigned mask = INT_WANTED;
2269 
2270 	if (mxfep->mxfe_wantw)
2271 		mask |= INT_TXOK;
2272 
2273 	if (MXFE_MODEL(mxfep) != MXFE_98713A)
2274 		mask |= INT_LINKSTATUS;
2275 
2276 	DBG(DINTR, "setting int mask to 0x%x", mask);
2277 	PUTCSR(mxfep, CSR_IER, mask);
2278 }
2279 
2280 void
2281 mxfe_disableinterrupts(mxfe_t *mxfep)
2282 {
2283 	/* disable further interrupts */
2284 	PUTCSR(mxfep, CSR_IER, 0);
2285 
2286 	/* clear any pending interrupts */
2287 	PUTCSR(mxfep, CSR_SR, INT_ALL);
2288 }
2289 
2290 void
2291 mxfe_send_setup(mxfe_t *mxfep)
2292 {
2293 	mxfe_txbuf_t	*txb;
2294 	mxfe_desc_t	*tmdp;
2295 
2296 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
2297 
2298 	/* setup frame -- must be at head of list -- guaranteed by caller! */
2299 	ASSERT(mxfep->mxfe_txsend == 0);
2300 
2301 	txb = mxfep->mxfe_txbufs[0];
2302 	tmdp = &mxfep->mxfe_txdescp[0];
2303 
2304 	bzero(txb->txb_buf, MXFE_SETUP_LEN);
2305 
2306 	/* program the unicast address */
2307 	txb->txb_buf[156] = mxfep->mxfe_curraddr[0];
2308 	txb->txb_buf[157] = mxfep->mxfe_curraddr[1];
2309 	txb->txb_buf[160] = mxfep->mxfe_curraddr[2];
2310 	txb->txb_buf[161] = mxfep->mxfe_curraddr[3];
2311 	txb->txb_buf[164] = mxfep->mxfe_curraddr[4];
2312 	txb->txb_buf[165] = mxfep->mxfe_curraddr[5];
2313 
2314 	/* make sure that the hardware can see it */
2315 	SYNCTXBUF(txb, MXFE_SETUP_LEN, DDI_DMA_SYNC_FORDEV);
2316 
2317 	PUTTXDESC(mxfep, tmdp->desc_control,
2318 	    TXCTL_FIRST | TXCTL_LAST | TXCTL_INTCMPLTE | TXCTL_HASHPERF |
2319 	    TXCTL_SETUP | MXFE_SETUP_LEN);
2320 
2321 	PUTTXDESC(mxfep, tmdp->desc_buffer1, txb->txb_paddr);
2322 	PUTTXDESC(mxfep, tmdp->desc_buffer2, 0);
2323 	PUTTXDESC(mxfep, tmdp->desc_status, TXSTAT_OWN);
2324 
2325 	/* sync the descriptor out to the device */
2326 	SYNCTXDESC(mxfep, 0, DDI_DMA_SYNC_FORDEV);
2327 
2328 	/*
2329 	 * wake up the chip ... inside the lock to protect against DR suspend,
2330 	 * etc.
2331 	 */
2332 	PUTCSR(mxfep, CSR_TDR, 0);
2333 	mxfep->mxfe_txsend++;
2334 	mxfep->mxfe_txavail--;
2335 
2336 	/*
2337 	 * Program promiscuous mode.
2338 	 */
2339 	if (mxfep->mxfe_promisc) {
2340 		SETBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
2341 	} else {
2342 		CLRBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
2343 	}
2344 }
2345 
2346 boolean_t
2347 mxfe_send(mxfe_t *mxfep, mblk_t *mp)
2348 {
2349 	size_t			len;
2350 	mxfe_txbuf_t		*txb;
2351 	mxfe_desc_t		*tmd;
2352 	uint32_t		control;
2353 	int			txsend;
2354 
2355 	ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
2356 	ASSERT(mp != NULL);
2357 
2358 	len = msgsize(mp);
2359 	if (len > ETHERVLANMTU) {
2360 		DBG(DXMIT, "frame too long: %d", len);
2361 		mxfep->mxfe_macxmt_errors++;
2362 		freemsg(mp);
2363 		return (B_TRUE);
2364 	}
2365 
2366 	if (mxfep->mxfe_txavail < MXFE_TXRECLAIM)
2367 		mxfe_reclaim(mxfep);
2368 
2369 	if (mxfep->mxfe_txavail == 0) {
2370 		/* no more tmds */
2371 		mxfep->mxfe_wantw = B_TRUE;
2372 		/* enable TX interrupt */
2373 		mxfe_enableinterrupts(mxfep);
2374 		return (B_FALSE);
2375 	}
2376 
2377 	txsend = mxfep->mxfe_txsend;
2378 
2379 	/*
2380 	 * For simplicity, we just do a copy into a preallocated
2381 	 * DMA buffer.
2382 	 */
2383 
2384 	txb = mxfep->mxfe_txbufs[txsend];
2385 	mcopymsg(mp, txb->txb_buf);	/* frees mp! */
2386 
2387 	/*
2388 	 * Statistics.
2389 	 */
2390 	mxfep->mxfe_opackets++;
2391 	mxfep->mxfe_obytes += len;
2392 	if (txb->txb_buf[0] & 0x1) {
2393 		if (bcmp(txb->txb_buf, mxfe_broadcast, ETHERADDRL) != 0)
2394 			mxfep->mxfe_multixmt++;
2395 		else
2396 			mxfep->mxfe_brdcstxmt++;
2397 	}
2398 
2399 	/* note len is already known to be a small unsigned */
2400 	control = len | TXCTL_FIRST | TXCTL_LAST | TXCTL_INTCMPLTE;
2401 
2402 	if (txsend == (MXFE_TXRING - 1))
2403 		control |= TXCTL_ENDRING;
2404 
2405 	tmd = &mxfep->mxfe_txdescp[txsend];
2406 
2407 	SYNCTXBUF(txb, len, DDI_DMA_SYNC_FORDEV);
2408 	PUTTXDESC(mxfep, tmd->desc_control, control);
2409 	PUTTXDESC(mxfep, tmd->desc_buffer1, txb->txb_paddr);
2410 	PUTTXDESC(mxfep, tmd->desc_buffer2, 0);
2411 	PUTTXDESC(mxfep, tmd->desc_status, TXSTAT_OWN);
2412 	/* sync the descriptor out to the device */
2413 	SYNCTXDESC(mxfep, txsend, DDI_DMA_SYNC_FORDEV);
2414 
2415 	/*
2416 	 * Note the new values of txavail and txsend.
2417 	 */
2418 	mxfep->mxfe_txavail--;
2419 	mxfep->mxfe_txsend = (txsend + 1) % MXFE_TXRING;
2420 
2421 	/*
2422 	 * It should never, ever take more than 5 seconds to drain
2423 	 * the ring.  If it happens, then we are stuck!
2424 	 */
2425 	mxfep->mxfe_txstall_time = gethrtime() + (5 * 1000000000ULL);
2426 
2427 	/*
2428 	 * wake up the chip ... inside the lock to protect against DR suspend,
2429 	 * etc.
2430 	 */
2431 	PUTCSR(mxfep, CSR_TDR, 0);
2432 
2433 	return (B_TRUE);
2434 }
2435 
2436 /*
2437  * Reclaim buffers that have completed transmission.
2438  */
2439 void
2440 mxfe_reclaim(mxfe_t *mxfep)
2441 {
2442 	mxfe_desc_t	*tmdp;
2443 
2444 	while (mxfep->mxfe_txavail != MXFE_TXRING) {
2445 		uint32_t	status;
2446 		uint32_t	control;
2447 		int		index = mxfep->mxfe_txreclaim;
2448 
2449 		tmdp = &mxfep->mxfe_txdescp[index];
2450 
2451 		/* sync it before we read it */
2452 		SYNCTXDESC(mxfep, index, DDI_DMA_SYNC_FORKERNEL);
2453 
2454 		control = GETTXDESC(mxfep, tmdp->desc_control);
2455 		status = GETTXDESC(mxfep, tmdp->desc_status);
2456 
2457 		if (status & TXSTAT_OWN) {
2458 			/* chip is still working on it, we're done */
2459 			break;
2460 		}
2461 
2462 		mxfep->mxfe_txavail++;
2463 		mxfep->mxfe_txreclaim = (index + 1) % MXFE_TXRING;
2464 
2465 		/* in the most common successful case, all bits are clear */
2466 		if (status == 0)
2467 			continue;
2468 
2469 		if (((control & TXCTL_SETUP) != 0) ||
2470 		    ((control & TXCTL_LAST) == 0)) {
2471 			/* no interesting statistics here */
2472 			continue;
2473 		}
2474 
2475 		if (status & TXSTAT_TXERR) {
2476 			mxfep->mxfe_errxmt++;
2477 
2478 			if (status & TXSTAT_JABBER) {
2479 				/* transmit jabber timeout */
2480 				mxfep->mxfe_macxmt_errors++;
2481 			}
2482 			if (status & (TXSTAT_CARRLOST | TXSTAT_NOCARR)) {
2483 				mxfep->mxfe_carrier_errors++;
2484 			}
2485 			if (status & TXSTAT_UFLOW) {
2486 				mxfep->mxfe_underflow++;
2487 			}
2488 			if (status & TXSTAT_LATECOL) {
2489 				mxfep->mxfe_tx_late_collisions++;
2490 			}
2491 			if (status & TXSTAT_EXCOLL) {
2492 				mxfep->mxfe_ex_collisions++;
2493 				mxfep->mxfe_collisions += 16;
2494 			}
2495 		}
2496 
2497 		if (status & TXSTAT_DEFER) {
2498 			mxfep->mxfe_defer_xmts++;
2499 		}
2500 
2501 		/* collision counting */
2502 		if (TXCOLLCNT(status) == 1) {
2503 			mxfep->mxfe_collisions++;
2504 			mxfep->mxfe_first_collisions++;
2505 		} else if (TXCOLLCNT(status)) {
2506 			mxfep->mxfe_collisions += TXCOLLCNT(status);
2507 			mxfep->mxfe_multi_collisions += TXCOLLCNT(status);
2508 		}
2509 	}
2510 
2511 	if (mxfep->mxfe_txavail >= MXFE_TXRESCHED) {
2512 		if (mxfep->mxfe_wantw) {
2513 			/*
2514 			 * we were able to reclaim some packets, so
2515 			 * disable tx interrupts
2516 			 */
2517 			mxfep->mxfe_wantw = B_FALSE;
2518 			mxfe_enableinterrupts(mxfep);
2519 			mac_tx_update(mxfep->mxfe_mh);
2520 		}
2521 	}
2522 }
2523 
2524 mblk_t *
2525 mxfe_receive(mxfe_t *mxfep)
2526 {
2527 	unsigned		len;
2528 	mxfe_rxbuf_t		*rxb;
2529 	mxfe_desc_t		*rmd;
2530 	uint32_t		status;
2531 	mblk_t			*mpchain, **mpp, *mp;
2532 	int			head, cnt;
2533 
2534 	mpchain = NULL;
2535 	mpp = &mpchain;
2536 	head = mxfep->mxfe_rxhead;
2537 
2538 	/* limit the number of packets we process to a ring size */
2539 	for (cnt = 0; cnt < MXFE_RXRING; cnt++) {
2540 
2541 		DBG(DRECV, "receive at index %d", head);
2542 
2543 		rmd = &mxfep->mxfe_rxdescp[head];
2544 		rxb = mxfep->mxfe_rxbufs[head];
2545 
2546 		SYNCRXDESC(mxfep, head, DDI_DMA_SYNC_FORKERNEL);
2547 		status = GETRXDESC(mxfep, rmd->desc_status);
2548 		if (status & RXSTAT_OWN) {
2549 			/* chip is still chewing on it */
2550 			break;
2551 		}
2552 
2553 		/* discard the ethernet frame checksum */
2554 		len = RXLENGTH(status) - ETHERFCSL;
2555 
2556 		DBG(DRECV, "recv length %d, status %x", len, status);
2557 
2558 		if ((status & (RXSTAT_ERRS | RXSTAT_FIRST | RXSTAT_LAST)) !=
2559 		    (RXSTAT_FIRST | RXSTAT_LAST)) {
2560 
2561 			mxfep->mxfe_errrcv++;
2562 
2563 			/*
2564 			 * Abnormal status bits detected, analyze further.
2565 			 */
2566 			if ((status & (RXSTAT_LAST|RXSTAT_FIRST)) !=
2567 			    (RXSTAT_LAST|RXSTAT_FIRST)) {
2568 				DBG(DRECV, "rx packet overspill");
2569 				if (status & RXSTAT_FIRST) {
2570 					mxfep->mxfe_toolong_errors++;
2571 				}
2572 			} else if (status & RXSTAT_DESCERR) {
2573 				mxfep->mxfe_macrcv_errors++;
2574 
2575 			} else if (status & RXSTAT_RUNT) {
2576 				mxfep->mxfe_runt++;
2577 
2578 			} else if (status & RXSTAT_COLLSEEN) {
2579 				/* this should really be rx_late_collisions */
2580 				mxfep->mxfe_macrcv_errors++;
2581 
2582 			} else if (status & RXSTAT_DRIBBLE) {
2583 				mxfep->mxfe_align_errors++;
2584 
2585 			} else if (status & RXSTAT_CRCERR) {
2586 				mxfep->mxfe_fcs_errors++;
2587 
2588 			} else if (status & RXSTAT_OFLOW) {
2589 				mxfep->mxfe_overflow++;
2590 			}
2591 		}
2592 
2593 		else if (len > ETHERVLANMTU) {
2594 			mxfep->mxfe_errrcv++;
2595 			mxfep->mxfe_toolong_errors++;
2596 		}
2597 
2598 		/*
2599 		 * At this point, the chip thinks the packet is OK.
2600 		 */
2601 		else {
2602 			mp = allocb(len + MXFE_HEADROOM, 0);
2603 			if (mp == NULL) {
2604 				mxfep->mxfe_errrcv++;
2605 				mxfep->mxfe_norcvbuf++;
2606 				goto skip;
2607 			}
2608 
2609 			/* sync the buffer before we look at it */
2610 			SYNCRXBUF(rxb, len, DDI_DMA_SYNC_FORKERNEL);
2611 			mp->b_rptr += MXFE_HEADROOM;
2612 			mp->b_wptr = mp->b_rptr + len;
2613 			bcopy((char *)rxb->rxb_buf, mp->b_rptr, len);
2614 
2615 			mxfep->mxfe_ipackets++;
2616 			mxfep->mxfe_rbytes += len;
2617 			if (status & RXSTAT_GROUP) {
2618 				if (bcmp(mp->b_rptr, mxfe_broadcast,
2619 				    ETHERADDRL) == 0)
2620 					mxfep->mxfe_brdcstrcv++;
2621 				else
2622 					mxfep->mxfe_multircv++;
2623 			}
2624 			*mpp = mp;
2625 			mpp = &mp->b_next;
2626 		}
2627 
2628 skip:
2629 		/* return ring entry to the hardware */
2630 		PUTRXDESC(mxfep, rmd->desc_status, RXSTAT_OWN);
2631 		SYNCRXDESC(mxfep, head, DDI_DMA_SYNC_FORDEV);
2632 
2633 		/* advance to next RMD */
2634 		head = (head + 1) % MXFE_RXRING;
2635 	}
2636 
2637 	mxfep->mxfe_rxhead = head;
2638 
2639 	return (mpchain);
2640 }
2641 
2642 int
2643 mxfe_m_stat(void *arg, uint_t stat, uint64_t *val)
2644 {
2645 	mxfe_t	*mxfep = arg;
2646 
2647 	mutex_enter(&mxfep->mxfe_xmtlock);
2648 	if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) == MXFE_RUNNING)
2649 		mxfe_reclaim(mxfep);
2650 	mutex_exit(&mxfep->mxfe_xmtlock);
2651 
2652 	switch (stat) {
2653 	case MAC_STAT_IFSPEED:
2654 		*val = mxfep->mxfe_ifspeed;
2655 		break;
2656 
2657 	case MAC_STAT_MULTIRCV:
2658 		*val = mxfep->mxfe_multircv;
2659 		break;
2660 
2661 	case MAC_STAT_BRDCSTRCV:
2662 		*val = mxfep->mxfe_brdcstrcv;
2663 		break;
2664 
2665 	case MAC_STAT_MULTIXMT:
2666 		*val = mxfep->mxfe_multixmt;
2667 		break;
2668 
2669 	case MAC_STAT_BRDCSTXMT:
2670 		*val = mxfep->mxfe_brdcstxmt;
2671 		break;
2672 
2673 	case MAC_STAT_IPACKETS:
2674 		*val = mxfep->mxfe_ipackets;
2675 		break;
2676 
2677 	case MAC_STAT_RBYTES:
2678 		*val = mxfep->mxfe_rbytes;
2679 		break;
2680 
2681 	case MAC_STAT_OPACKETS:
2682 		*val = mxfep->mxfe_opackets;
2683 		break;
2684 
2685 	case MAC_STAT_OBYTES:
2686 		*val = mxfep->mxfe_obytes;
2687 		break;
2688 
2689 	case MAC_STAT_NORCVBUF:
2690 		*val = mxfep->mxfe_norcvbuf;
2691 		break;
2692 
2693 	case MAC_STAT_NOXMTBUF:
2694 		*val = mxfep->mxfe_noxmtbuf;
2695 		break;
2696 
2697 	case MAC_STAT_COLLISIONS:
2698 		*val = mxfep->mxfe_collisions;
2699 		break;
2700 
2701 	case MAC_STAT_IERRORS:
2702 		*val = mxfep->mxfe_errrcv;
2703 		break;
2704 
2705 	case MAC_STAT_OERRORS:
2706 		*val = mxfep->mxfe_errxmt;
2707 		break;
2708 
2709 	case ETHER_STAT_LINK_DUPLEX:
2710 		*val = mxfep->mxfe_duplex;
2711 		break;
2712 
2713 	case ETHER_STAT_ALIGN_ERRORS:
2714 		*val = mxfep->mxfe_align_errors;
2715 		break;
2716 
2717 	case ETHER_STAT_FCS_ERRORS:
2718 		*val = mxfep->mxfe_fcs_errors;
2719 		break;
2720 
2721 	case ETHER_STAT_SQE_ERRORS:
2722 		*val = mxfep->mxfe_sqe_errors;
2723 		break;
2724 
2725 	case ETHER_STAT_DEFER_XMTS:
2726 		*val = mxfep->mxfe_defer_xmts;
2727 		break;
2728 
2729 	case ETHER_STAT_FIRST_COLLISIONS:
2730 		*val  = mxfep->mxfe_first_collisions;
2731 		break;
2732 
2733 	case ETHER_STAT_MULTI_COLLISIONS:
2734 		*val = mxfep->mxfe_multi_collisions;
2735 		break;
2736 
2737 	case ETHER_STAT_TX_LATE_COLLISIONS:
2738 		*val = mxfep->mxfe_tx_late_collisions;
2739 		break;
2740 
2741 	case ETHER_STAT_EX_COLLISIONS:
2742 		*val = mxfep->mxfe_ex_collisions;
2743 		break;
2744 
2745 	case ETHER_STAT_MACXMT_ERRORS:
2746 		*val = mxfep->mxfe_macxmt_errors;
2747 		break;
2748 
2749 	case ETHER_STAT_CARRIER_ERRORS:
2750 		*val = mxfep->mxfe_carrier_errors;
2751 		break;
2752 
2753 	case ETHER_STAT_TOOLONG_ERRORS:
2754 		*val = mxfep->mxfe_toolong_errors;
2755 		break;
2756 
2757 	case ETHER_STAT_MACRCV_ERRORS:
2758 		*val = mxfep->mxfe_macrcv_errors;
2759 		break;
2760 
2761 	case MAC_STAT_OVERFLOWS:
2762 		*val = mxfep->mxfe_overflow;
2763 		break;
2764 
2765 	case MAC_STAT_UNDERFLOWS:
2766 		*val = mxfep->mxfe_underflow;
2767 		break;
2768 
2769 	case ETHER_STAT_TOOSHORT_ERRORS:
2770 		*val = mxfep->mxfe_runt;
2771 		break;
2772 
2773 	case ETHER_STAT_JABBER_ERRORS:
2774 		*val = mxfep->mxfe_jabber;
2775 		break;
2776 
2777 	case ETHER_STAT_CAP_100T4:
2778 		*val = mxfep->mxfe_bmsr & MII_STATUS_100_BASE_T4 ? 1 : 0;
2779 		break;
2780 
2781 	case ETHER_STAT_ADV_CAP_100T4:
2782 		*val = mxfep->mxfe_adv_100T4;
2783 		break;
2784 
2785 	case ETHER_STAT_LP_CAP_100T4:
2786 		*val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_T4) ? 1 : 0;
2787 		break;
2788 
2789 	case ETHER_STAT_CAP_100FDX:
2790 		*val = mxfep->mxfe_bmsr & MII_STATUS_100_BASEX_FD ? 1 : 0;
2791 		break;
2792 
2793 	case ETHER_STAT_CAP_100HDX:
2794 		*val = mxfep->mxfe_bmsr & MII_STATUS_100_BASEX ? 1 : 0;
2795 		break;
2796 
2797 	case ETHER_STAT_CAP_10FDX:
2798 		*val = mxfep->mxfe_bmsr & MII_STATUS_10_FD ? 1 : 0;
2799 		break;
2800 
2801 	case ETHER_STAT_CAP_10HDX:
2802 		*val = mxfep->mxfe_bmsr & MII_STATUS_10 ? 1 : 0;
2803 		break;
2804 
2805 	case ETHER_STAT_CAP_AUTONEG:
2806 		*val = mxfep->mxfe_bmsr & MII_STATUS_CANAUTONEG ? 1 : 0;
2807 		break;
2808 
2809 	case ETHER_STAT_LINK_AUTONEG:
2810 		*val = ((mxfep->mxfe_adv_aneg != 0) &&
2811 		    ((mxfep->mxfe_aner & MII_AN_EXP_LPCANAN) != 0));
2812 		break;
2813 
2814 	case ETHER_STAT_ADV_CAP_100FDX:
2815 		*val = mxfep->mxfe_adv_100fdx;
2816 		break;
2817 
2818 	case ETHER_STAT_ADV_CAP_100HDX:
2819 		*val = mxfep->mxfe_adv_100hdx;
2820 		break;
2821 
2822 	case ETHER_STAT_ADV_CAP_10FDX:
2823 		*val = mxfep->mxfe_adv_10fdx;
2824 		break;
2825 
2826 	case ETHER_STAT_ADV_CAP_10HDX:
2827 		*val = mxfep->mxfe_adv_10hdx;
2828 		break;
2829 
2830 	case ETHER_STAT_ADV_CAP_AUTONEG:
2831 		*val = mxfep->mxfe_adv_aneg;
2832 		break;
2833 
2834 	case ETHER_STAT_LP_CAP_100FDX:
2835 		*val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_TX_FD) ? 1 : 0;
2836 		break;
2837 
2838 	case ETHER_STAT_LP_CAP_100HDX:
2839 		*val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_TX) ? 1 : 0;
2840 		break;
2841 
2842 	case ETHER_STAT_LP_CAP_10FDX:
2843 		*val = (mxfep->mxfe_anlpar & MII_ABILITY_10BASE_T_FD) ? 1 : 0;
2844 		break;
2845 
2846 	case ETHER_STAT_LP_CAP_10HDX:
2847 		*val = (mxfep->mxfe_anlpar & MII_ABILITY_10BASE_T) ? 1 : 0;
2848 		break;
2849 
2850 	case ETHER_STAT_LP_CAP_AUTONEG:
2851 		*val = (mxfep->mxfe_aner & MII_AN_EXP_LPCANAN) ? 1 : 0;
2852 		break;
2853 
2854 	case ETHER_STAT_XCVR_ADDR:
2855 		*val = mxfep->mxfe_phyaddr;
2856 		break;
2857 
2858 	case ETHER_STAT_XCVR_ID:
2859 		*val = mxfep->mxfe_phyid;
2860 		break;
2861 
2862 	case ETHER_STAT_XCVR_INUSE:
2863 		*val = mxfep->mxfe_phyinuse;
2864 		break;
2865 
2866 	default:
2867 		return (ENOTSUP);
2868 	}
2869 	return (0);
2870 }
2871 
2872 /*
2873  * NDD support.
2874  */
2875 mxfe_nd_t *
2876 mxfe_ndfind(mxfe_t *mxfep, char *name)
2877 {
2878 	mxfe_nd_t	*ndp;
2879 
2880 	for (ndp = mxfep->mxfe_ndp; ndp != NULL; ndp = ndp->nd_next) {
2881 		if (strcmp(name, ndp->nd_name) == 0) {
2882 			break;
2883 		}
2884 	}
2885 	return (ndp);
2886 }
2887 
2888 void
2889 mxfe_ndadd(mxfe_t *mxfep, char *name, mxfe_nd_pf_t get, mxfe_nd_pf_t set,
2890     intptr_t arg1, intptr_t arg2)
2891 {
2892 	mxfe_nd_t	*newndp;
2893 	mxfe_nd_t	**ndpp;
2894 
2895 	newndp = (mxfe_nd_t *)kmem_alloc(sizeof (mxfe_nd_t), KM_SLEEP);
2896 	newndp->nd_next = NULL;
2897 	newndp->nd_name = name;
2898 	newndp->nd_get = get;
2899 	newndp->nd_set = set;
2900 	newndp->nd_arg1 = arg1;
2901 	newndp->nd_arg2 = arg2;
2902 
2903 	/* seek to the end of the list */
2904 	for (ndpp = &mxfep->mxfe_ndp; *ndpp; ndpp = &(*ndpp)->nd_next) {
2905 	}
2906 
2907 	*ndpp = newndp;
2908 }
2909 
2910 void
2911 mxfe_ndempty(mblk_t *mp)
2912 {
2913 	while (mp != NULL) {
2914 		mp->b_rptr = mp->b_datap->db_base;
2915 		mp->b_wptr = mp->b_rptr;
2916 		mp = mp->b_cont;
2917 	}
2918 }
2919 
2920 void
2921 mxfe_ndget(mxfe_t *mxfep, queue_t *wq, mblk_t *mp)
2922 {
2923 	mblk_t		*nmp = mp->b_cont;
2924 	mxfe_nd_t	*ndp;
2925 	int		rv;
2926 	char		name[128];
2927 
2928 	/* assumption, name will fit in first mblk of chain */
2929 	if ((nmp == NULL) || (nmp->b_wptr <= nmp->b_rptr)) {
2930 		miocnak(wq, mp, 0, EINVAL);
2931 		return;
2932 	}
2933 
2934 	if (mxfe_ndparselen(nmp) >= sizeof (name)) {
2935 		miocnak(wq, mp, 0, EINVAL);
2936 		return;
2937 	}
2938 	mxfe_ndparsestring(nmp, name, sizeof (name));
2939 
2940 	/* locate variable */
2941 	if ((ndp = mxfe_ndfind(mxfep, name)) == NULL) {
2942 		miocnak(wq, mp, 0, EINVAL);
2943 		return;
2944 	}
2945 
2946 	/* locate get callback */
2947 	if (ndp->nd_get == NULL) {
2948 		miocnak(wq, mp, 0, EACCES);
2949 		return;
2950 	}
2951 
2952 	/* clear the result buffer */
2953 	mxfe_ndempty(nmp);
2954 
2955 	rv = (*ndp->nd_get)(mxfep, nmp, ndp);
2956 	if (rv == 0) {
2957 		/* add final null bytes */
2958 		rv = mxfe_ndaddbytes(nmp, "\0", 1);
2959 	}
2960 
2961 	if (rv == 0) {
2962 		miocack(wq, mp, msgsize(nmp), 0);
2963 	} else {
2964 		miocnak(wq, mp, 0, rv);
2965 	}
2966 }
2967 
2968 void
2969 mxfe_ndset(mxfe_t *mxfep, queue_t *wq, mblk_t *mp)
2970 {
2971 	struct iocblk	*iocp = (void *)mp->b_rptr;
2972 	mblk_t		*nmp = mp->b_cont;
2973 	mxfe_nd_t	*ndp;
2974 	int		rv;
2975 	char		name[128];
2976 
2977 	/* enforce policy */
2978 	if ((rv = priv_getbyname(PRIV_SYS_NET_CONFIG, 0)) < 0) {
2979 		/* priv_getbyname returns a negative errno */
2980 		miocnak(wq, mp, 0, -rv);
2981 		return;
2982 	}
2983 	if ((rv = priv_policy(iocp->ioc_cr, rv, B_FALSE, EPERM, NULL)) != 0) {
2984 		miocnak(wq, mp, 0, rv);
2985 		return;
2986 	}
2987 
2988 	/* assumption, name will fit in first mblk of chain */
2989 	if ((nmp == NULL) || (nmp->b_wptr <= nmp->b_rptr)) {
2990 		miocnak(wq, mp, 0, EINVAL);
2991 		return;
2992 	}
2993 
2994 	if (mxfe_ndparselen(nmp) >= sizeof (name)) {
2995 		miocnak(wq, mp, 0, EINVAL);
2996 		return;
2997 	}
2998 	mxfe_ndparsestring(nmp, name, sizeof (name));
2999 
3000 	/* locate variable */
3001 	if ((ndp = mxfe_ndfind(mxfep, name)) == NULL) {
3002 		miocnak(wq, mp, 0, EINVAL);
3003 		return;
3004 	}
3005 
3006 	/* locate set callback */
3007 	if (ndp->nd_set == NULL) {
3008 		miocnak(wq, mp, 0, EACCES);
3009 		return;
3010 	}
3011 
3012 	rv = (*ndp->nd_set)(mxfep, nmp, ndp);
3013 
3014 	if (rv == 0) {
3015 		miocack(wq, mp, 0, 0);
3016 	} else {
3017 		miocnak(wq, mp, 0, rv);
3018 	}
3019 }
3020 
3021 int
3022 mxfe_ndaddbytes(mblk_t *mp, char *bytes, int cnt)
3023 {
3024 	int index;
3025 
3026 	for (index = 0; index < cnt; index++) {
3027 		while (mp && (mp->b_wptr >= DB_LIM(mp))) {
3028 			mp = mp->b_cont;
3029 		}
3030 		if (mp == NULL) {
3031 			return (ENOSPC);
3032 		}
3033 		*(mp->b_wptr) = *bytes;
3034 		mp->b_wptr++;
3035 		bytes++;
3036 	}
3037 	return (0);
3038 }
3039 
3040 int
3041 mxfe_ndaddstr(mblk_t *mp, char *str, int addnull)
3042 {
3043 	/* store the string, plus the terminating null */
3044 	return (mxfe_ndaddbytes(mp, str, strlen(str) + (addnull ? 1 : 0)));
3045 }
3046 
3047 int
3048 mxfe_ndparselen(mblk_t *mp)
3049 {
3050 	int	len = 0;
3051 	int	done = 0;
3052 	uchar_t	*ptr;
3053 
3054 	while (mp && !done) {
3055 		for (ptr = mp->b_rptr; ptr < mp->b_wptr; ptr++) {
3056 			if (!(*ptr)) {
3057 				done = 1;
3058 				break;
3059 			}
3060 			len++;
3061 		}
3062 		mp = mp->b_cont;
3063 	}
3064 	return (len);
3065 }
3066 
3067 int
3068 mxfe_ndparseint(mblk_t *mp)
3069 {
3070 	int	done = 0;
3071 	int	val = 0;
3072 	while (mp && !done) {
3073 		while (mp->b_rptr < mp->b_wptr) {
3074 			uchar_t ch = *(mp->b_rptr);
3075 			mp->b_rptr++;
3076 			if ((ch >= '0') && (ch <= '9')) {
3077 				val *= 10;
3078 				val += ch - '0';
3079 			} else if (ch == 0) {
3080 				return (val);
3081 			} else {
3082 				/* parse error, put back rptr */
3083 				mp->b_rptr--;
3084 				return (val);
3085 			}
3086 		}
3087 		mp = mp->b_cont;
3088 	}
3089 	return (val);
3090 }
3091 
3092 void
3093 mxfe_ndparsestring(mblk_t *mp, char *buf, int maxlen)
3094 {
3095 	int	done = 0;
3096 	int	len = 0;
3097 
3098 	/* ensure null termination */
3099 	buf[maxlen - 1] = 0;
3100 	while (mp && !done) {
3101 		while (mp->b_rptr < mp->b_wptr) {
3102 			char ch = *((char *)mp->b_rptr);
3103 			mp->b_rptr++;
3104 			buf[len++] = ch;
3105 			if ((ch == 0) || (len == maxlen)) {
3106 				return;
3107 			}
3108 		}
3109 		mp = mp->b_cont;
3110 	}
3111 }
3112 
3113 int
3114 mxfe_ndquestion(mxfe_t *mxfep, mblk_t *mp, mxfe_nd_t *ndp)
3115 {
3116 	for (ndp = mxfep->mxfe_ndp; ndp; ndp = ndp->nd_next) {
3117 		int	rv;
3118 		char	*s;
3119 		if ((rv = mxfe_ndaddstr(mp, ndp->nd_name, 0)) != 0) {
3120 			return (rv);
3121 		}
3122 		if (ndp->nd_get && ndp->nd_set) {
3123 			s = " (read and write)";
3124 		} else if (ndp->nd_get) {
3125 			s = " (read only)";
3126 		} else if (ndp->nd_set) {
3127 			s = " (write only)";
3128 		} else {
3129 			s = " (no read or write)";
3130 		}
3131 		if ((rv = mxfe_ndaddstr(mp, s, 1)) != 0) {
3132 			return (rv);
3133 		}
3134 	}
3135 	return (0);
3136 }
3137 
3138 /*ARGSUSED*/
3139 int
3140 mxfe_ndgetint(mxfe_t *mxfep, mblk_t *mp, mxfe_nd_t *ndp)
3141 {
3142 	int		val;
3143 	char		buf[16];
3144 
3145 	val = *(int *)ndp->nd_arg1;
3146 
3147 	(void) snprintf(buf, sizeof (buf), "%d", val);
3148 	return (mxfe_ndaddstr(mp, buf, 1));
3149 }
3150 
3151 /*ARGSUSED*/
3152 int
3153 mxfe_ndgetbit(mxfe_t *mxfep, mblk_t *mp, mxfe_nd_t *ndp)
3154 {
3155 	unsigned	val;
3156 	unsigned	mask;
3157 
3158 	val = *(unsigned *)ndp->nd_arg1;
3159 	mask = (unsigned)ndp->nd_arg2;
3160 
3161 	return (mxfe_ndaddstr(mp, val & mask ? "1" : "0", 1));
3162 }
3163 
3164 int
3165 mxfe_ndsetadv(mxfe_t *mxfep, mblk_t *mp, mxfe_nd_t *ndp)
3166 {
3167 	unsigned	*ptr = (unsigned *)ndp->nd_arg1;
3168 	unsigned	oldval, newval;
3169 
3170 	newval = mxfe_ndparseint(mp) ? 1 : 0;
3171 
3172 	mutex_enter(&mxfep->mxfe_intrlock);
3173 	mutex_enter(&mxfep->mxfe_xmtlock);
3174 
3175 	oldval = *ptr;
3176 	if (oldval != newval) {
3177 		*ptr = newval;
3178 		if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) ==
3179 		    MXFE_RUNNING) {
3180 			/*
3181 			 * This re-initializes the phy, but it also
3182 			 * restarts transmit and receive rings.
3183 			 * Needless to say, changing the link
3184 			 * parameters is destructive to traffic in
3185 			 * progress.
3186 			 */
3187 			mxfe_resetall(mxfep);
3188 		}
3189 	}
3190 	mutex_exit(&mxfep->mxfe_xmtlock);
3191 	mutex_exit(&mxfep->mxfe_intrlock);
3192 
3193 	return (0);
3194 }
3195 
3196 void
3197 mxfe_ndfini(mxfe_t *mxfep)
3198 {
3199 	mxfe_nd_t	*ndp;
3200 
3201 	while ((ndp = mxfep->mxfe_ndp) != NULL) {
3202 		mxfep->mxfe_ndp = ndp->nd_next;
3203 		kmem_free(ndp, sizeof (mxfe_nd_t));
3204 	}
3205 }
3206 
3207 void
3208 mxfe_ndinit(mxfe_t *mxfep)
3209 {
3210 	mxfe_ndadd(mxfep, "?", mxfe_ndquestion, NULL, 0, 0);
3211 	mxfe_ndadd(mxfep, "link_status", mxfe_ndgetint, NULL,
3212 	    (intptr_t)&mxfep->mxfe_linkup, 0);
3213 	mxfe_ndadd(mxfep, "link_speed", mxfe_ndgetint, NULL,
3214 	    (intptr_t)&mxfep->mxfe_ifspeed, 0);
3215 	mxfe_ndadd(mxfep, "link_duplex", mxfe_ndgetint, NULL,
3216 	    (intptr_t)&mxfep->mxfe_duplex, 0);
3217 	mxfe_ndadd(mxfep, "adv_autoneg_cap", mxfe_ndgetint, mxfe_ndsetadv,
3218 	    (intptr_t)&mxfep->mxfe_adv_aneg, 0);
3219 	mxfe_ndadd(mxfep, "adv_100T4_cap", mxfe_ndgetint, mxfe_ndsetadv,
3220 	    (intptr_t)&mxfep->mxfe_adv_100T4, 0);
3221 	mxfe_ndadd(mxfep, "adv_100fdx_cap", mxfe_ndgetint, mxfe_ndsetadv,
3222 	    (intptr_t)&mxfep->mxfe_adv_100fdx, 0);
3223 	mxfe_ndadd(mxfep, "adv_100hdx_cap", mxfe_ndgetint, mxfe_ndsetadv,
3224 	    (intptr_t)&mxfep->mxfe_adv_100hdx, 0);
3225 	mxfe_ndadd(mxfep, "adv_10fdx_cap",  mxfe_ndgetint, mxfe_ndsetadv,
3226 	    (intptr_t)&mxfep->mxfe_adv_10fdx, 0);
3227 	mxfe_ndadd(mxfep, "adv_10hdx_cap",  mxfe_ndgetint, mxfe_ndsetadv,
3228 	    (intptr_t)&mxfep->mxfe_adv_10hdx, 0);
3229 	mxfe_ndadd(mxfep, "autoneg_cap", mxfe_ndgetbit, NULL,
3230 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_CANAUTONEG);
3231 	mxfe_ndadd(mxfep, "100T4_cap", mxfe_ndgetbit, NULL,
3232 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_100_BASE_T4);
3233 	mxfe_ndadd(mxfep, "100fdx_cap", mxfe_ndgetbit, NULL,
3234 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_100_BASEX_FD);
3235 	mxfe_ndadd(mxfep, "100hdx_cap", mxfe_ndgetbit, NULL,
3236 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_100_BASEX);
3237 	mxfe_ndadd(mxfep, "10fdx_cap", mxfe_ndgetbit, NULL,
3238 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_10_FD);
3239 	mxfe_ndadd(mxfep, "10hdx_cap", mxfe_ndgetbit, NULL,
3240 	    (intptr_t)&mxfep->mxfe_bmsr, MII_STATUS_10);
3241 	mxfe_ndadd(mxfep, "lp_autoneg_cap", mxfe_ndgetbit, NULL,
3242 	    (intptr_t)&mxfep->mxfe_aner, MII_AN_EXP_LPCANAN);
3243 	mxfe_ndadd(mxfep, "lp_100T4_cap", mxfe_ndgetbit, NULL,
3244 	    (intptr_t)&mxfep->mxfe_anlpar, MII_ABILITY_100BASE_T4);
3245 	mxfe_ndadd(mxfep, "lp_100fdx_cap", mxfe_ndgetbit, NULL,
3246 	    (intptr_t)&mxfep->mxfe_anlpar, MII_ABILITY_100BASE_TX_FD);
3247 	mxfe_ndadd(mxfep, "lp_100hdx_cap", mxfe_ndgetbit, NULL,
3248 	    (intptr_t)&mxfep->mxfe_anlpar, MII_ABILITY_100BASE_TX);
3249 	mxfe_ndadd(mxfep, "lp_10fdx_cap", mxfe_ndgetbit, NULL,
3250 	    (intptr_t)&mxfep->mxfe_anlpar, MII_ABILITY_10BASE_T_FD);
3251 	mxfe_ndadd(mxfep, "lp_10hdx_cap", mxfe_ndgetbit, NULL,
3252 	    (intptr_t)&mxfep->mxfe_anlpar, MII_ABILITY_10BASE_T);
3253 }
3254 
3255 /*
3256  * Debugging and error reporting.
3257  */
3258 void
3259 mxfe_error(dev_info_t *dip, char *fmt, ...)
3260 {
3261 	va_list	ap;
3262 	char	buf[256];
3263 
3264 	va_start(ap, fmt);
3265 	(void) vsnprintf(buf, sizeof (buf), fmt, ap);
3266 	va_end(ap);
3267 
3268 	if (dip) {
3269 		cmn_err(CE_WARN, "%s%d: %s",
3270 		    ddi_driver_name(dip), ddi_get_instance(dip), buf);
3271 	} else {
3272 		cmn_err(CE_WARN, "mxfe: %s", buf);
3273 	}
3274 }
3275 
3276 #ifdef DEBUG
3277 
3278 void
3279 mxfe_dprintf(mxfe_t *mxfep, const char *func, int level, char *fmt, ...)
3280 {
3281 	va_list	ap;
3282 
3283 	va_start(ap, fmt);
3284 	if (mxfe_debug & level) {
3285 		char	tag[64];
3286 		char	buf[256];
3287 
3288 		if (mxfep && mxfep->mxfe_dip) {
3289 			(void) snprintf(tag, sizeof (tag),
3290 			    "%s%d", ddi_driver_name(mxfep->mxfe_dip),
3291 			    ddi_get_instance(mxfep->mxfe_dip));
3292 		} else {
3293 			(void) snprintf(tag, sizeof (tag), "mxfe");
3294 		}
3295 
3296 		(void) snprintf(buf, sizeof (buf), "%s: %s: %s\n", tag,
3297 		    func, fmt);
3298 
3299 		vcmn_err(CE_CONT, buf, ap);
3300 	}
3301 	va_end(ap);
3302 }
3303 
3304 #endif
3305