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