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