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