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