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