Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / mxfe / mxfe.c
blob790c936fd57cc5dd9ba954f0c0ee28e7f4900100
1 /*
2 * Solaris driver for ethernet cards based on the Macronix 98715
4 * Copyright (c) 2007 by Garrett D'Amore <garrett@damore.org>.
5 * All rights reserved.
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.
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.
32 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
33 * Use is subject to license terms.
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>
57 #include "mxfe.h"
58 #include "mxfeimpl.h"
61 * Driver globals.
64 /* patchable debug flag ... must not be static! */
65 #ifdef DEBUG
66 unsigned mxfe_debug = DWARN;
67 #endif
69 /* table of supported devices */
70 static mxfe_card_t mxfe_cards[] = {
73 * Lite-On products
75 { 0x11ad, 0xc115, 0, 0, "Lite-On LC82C115", MXFE_PNICII },
78 * Macronix chips
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 },
88 * Compex (relabeled Macronix products)
90 { 0x11fc, 0x9881, 0x00, 0x00, "Compex 9881", MXFE_98713 },
91 { 0x11fc, 0x9881, 0x10, 0xff, "Compex 9881A", MXFE_98713A },
93 * Models listed here
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 },
100 #define ETHERVLANMTU (ETHERMAX + 4)
103 * Function prototypes
105 static int mxfe_attach(dev_info_t *, ddi_attach_cmd_t);
106 static int mxfe_detach(dev_info_t *, ddi_detach_cmd_t);
107 static int mxfe_resume(dev_info_t *);
108 static int mxfe_quiesce(dev_info_t *);
109 static int mxfe_m_unicst(void *, const uint8_t *);
110 static int mxfe_m_multicst(void *, boolean_t, const uint8_t *);
111 static int mxfe_m_promisc(void *, boolean_t);
112 static mblk_t *mxfe_m_tx(void *, mblk_t *);
113 static int mxfe_m_stat(void *, uint_t, uint64_t *);
114 static int mxfe_m_start(void *);
115 static void mxfe_m_stop(void *);
116 static int mxfe_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
117 void *);
118 static int mxfe_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
119 const void *);
120 static void mxfe_m_propinfo(void *, const char *, mac_prop_id_t,
121 mac_prop_info_handle_t);
122 static unsigned mxfe_intr(caddr_t);
123 static void mxfe_startmac(mxfe_t *);
124 static void mxfe_stopmac(mxfe_t *);
125 static void mxfe_resetrings(mxfe_t *);
126 static boolean_t mxfe_initialize(mxfe_t *);
127 static void mxfe_startall(mxfe_t *);
128 static void mxfe_stopall(mxfe_t *);
129 static void mxfe_resetall(mxfe_t *);
130 static mxfe_txbuf_t *mxfe_alloctxbuf(mxfe_t *);
131 static void mxfe_destroytxbuf(mxfe_txbuf_t *);
132 static mxfe_rxbuf_t *mxfe_allocrxbuf(mxfe_t *);
133 static void mxfe_destroyrxbuf(mxfe_rxbuf_t *);
134 static void mxfe_send_setup(mxfe_t *);
135 static boolean_t mxfe_send(mxfe_t *, mblk_t *);
136 static int mxfe_allocrxring(mxfe_t *);
137 static void mxfe_freerxring(mxfe_t *);
138 static int mxfe_alloctxring(mxfe_t *);
139 static void mxfe_freetxring(mxfe_t *);
140 static void mxfe_error(dev_info_t *, char *, ...);
141 static uint8_t mxfe_sromwidth(mxfe_t *);
142 static uint16_t mxfe_readsromword(mxfe_t *, unsigned);
143 static void mxfe_readsrom(mxfe_t *, unsigned, unsigned, void *);
144 static void mxfe_getfactaddr(mxfe_t *, uchar_t *);
145 static uint8_t mxfe_miireadbit(mxfe_t *);
146 static void mxfe_miiwritebit(mxfe_t *, uint8_t);
147 static void mxfe_miitristate(mxfe_t *);
148 static uint16_t mxfe_miiread(mxfe_t *, int, int);
149 static void mxfe_miiwrite(mxfe_t *, int, int, uint16_t);
150 static uint16_t mxfe_miireadgeneral(mxfe_t *, int, int);
151 static void mxfe_miiwritegeneral(mxfe_t *, int, int, uint16_t);
152 static uint16_t mxfe_miiread98713(mxfe_t *, int, int);
153 static void mxfe_miiwrite98713(mxfe_t *, int, int, uint16_t);
154 static void mxfe_startphy(mxfe_t *);
155 static void mxfe_stopphy(mxfe_t *);
156 static void mxfe_startphymii(mxfe_t *);
157 static void mxfe_startphynway(mxfe_t *);
158 static void mxfe_startnway(mxfe_t *);
159 static void mxfe_reportlink(mxfe_t *);
160 static void mxfe_checklink(mxfe_t *);
161 static void mxfe_checklinkmii(mxfe_t *);
162 static void mxfe_checklinknway(mxfe_t *);
163 static void mxfe_disableinterrupts(mxfe_t *);
164 static void mxfe_enableinterrupts(mxfe_t *);
165 static void mxfe_reclaim(mxfe_t *);
166 static boolean_t mxfe_receive(mxfe_t *, mblk_t **);
168 #ifdef DEBUG
169 static void mxfe_dprintf(mxfe_t *, const char *, int, char *, ...);
170 #endif
172 #define KIOIP KSTAT_INTR_PTR(mxfep->mxfe_intrstat)
174 static mac_callbacks_t mxfe_m_callbacks = {
175 MC_SETPROP | MC_GETPROP | MC_PROPINFO,
176 mxfe_m_stat,
177 mxfe_m_start,
178 mxfe_m_stop,
179 mxfe_m_promisc,
180 mxfe_m_multicst,
181 mxfe_m_unicst,
182 mxfe_m_tx,
183 NULL,
184 NULL, /* mc_ioctl */
185 NULL, /* mc_getcapab */
186 NULL, /* mc_open */
187 NULL, /* mc_close */
188 mxfe_m_setprop,
189 mxfe_m_getprop,
190 mxfe_m_propinfo
194 * Stream information
196 DDI_DEFINE_STREAM_OPS(mxfe_devops, nulldev, nulldev, mxfe_attach, mxfe_detach,
197 nodev, NULL, D_MP, NULL, mxfe_quiesce);
200 * Module linkage information.
203 static struct modldrv mxfe_modldrv = {
204 &mod_driverops, /* drv_modops */
205 "Macronix Fast Ethernet", /* drv_linkinfo */
206 &mxfe_devops /* drv_dev_ops */
209 static struct modlinkage mxfe_modlinkage = {
210 MODREV_1, /* ml_rev */
211 { &mxfe_modldrv, NULL } /* ml_linkage */
215 * Device attributes.
217 static ddi_device_acc_attr_t mxfe_devattr = {
218 DDI_DEVICE_ATTR_V0,
219 DDI_STRUCTURE_LE_ACC,
220 DDI_STRICTORDER_ACC
223 static ddi_device_acc_attr_t mxfe_bufattr = {
224 DDI_DEVICE_ATTR_V0,
225 DDI_NEVERSWAP_ACC,
226 DDI_STRICTORDER_ACC
229 static ddi_dma_attr_t mxfe_dma_attr = {
230 DMA_ATTR_V0, /* dma_attr_version */
231 0, /* dma_attr_addr_lo */
232 0xFFFFFFFFU, /* dma_attr_addr_hi */
233 0x7FFFFFFFU, /* dma_attr_count_max */
234 4, /* dma_attr_align */
235 0x3F, /* dma_attr_burstsizes */
236 1, /* dma_attr_minxfer */
237 0xFFFFFFFFU, /* dma_attr_maxxfer */
238 0xFFFFFFFFU, /* dma_attr_seg */
239 1, /* dma_attr_sgllen */
240 1, /* dma_attr_granular */
241 0 /* dma_attr_flags */
245 * Tx buffers can be arbitrarily aligned. Additionally, they can
246 * cross a page boundary, so we use the two buffer addresses of the
247 * chip to provide a two-entry scatter-gather list.
249 static ddi_dma_attr_t mxfe_dma_txattr = {
250 DMA_ATTR_V0, /* dma_attr_version */
251 0, /* dma_attr_addr_lo */
252 0xFFFFFFFFU, /* dma_attr_addr_hi */
253 0x7FFFFFFFU, /* dma_attr_count_max */
254 1, /* dma_attr_align */
255 0x3F, /* dma_attr_burstsizes */
256 1, /* dma_attr_minxfer */
257 0xFFFFFFFFU, /* dma_attr_maxxfer */
258 0xFFFFFFFFU, /* dma_attr_seg */
259 2, /* dma_attr_sgllen */
260 1, /* dma_attr_granular */
261 0 /* dma_attr_flags */
265 * Ethernet addresses.
267 static uchar_t mxfe_broadcast[ETHERADDRL] = {
268 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
272 * DDI entry points.
275 _init(void)
277 int rv;
278 mac_init_ops(&mxfe_devops, "mxfe");
279 if ((rv = mod_install(&mxfe_modlinkage)) != DDI_SUCCESS) {
280 mac_fini_ops(&mxfe_devops);
282 return (rv);
286 _fini(void)
288 int rv;
289 if ((rv = mod_remove(&mxfe_modlinkage)) == DDI_SUCCESS) {
290 mac_fini_ops(&mxfe_devops);
292 return (rv);
296 _info(struct modinfo *modinfop)
298 return (mod_info(&mxfe_modlinkage, modinfop));
302 mxfe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
304 mxfe_t *mxfep;
305 mac_register_t *macp;
306 int inst = ddi_get_instance(dip);
307 ddi_acc_handle_t pci;
308 uint16_t venid;
309 uint16_t devid;
310 uint16_t revid;
311 uint16_t svid;
312 uint16_t ssid;
313 uint16_t cachesize;
314 mxfe_card_t *cardp;
315 int i;
317 switch (cmd) {
318 case DDI_RESUME:
319 return (mxfe_resume(dip));
321 case DDI_ATTACH:
322 break;
324 default:
325 return (DDI_FAILURE);
328 /* this card is a bus master, reject any slave-only slot */
329 if (ddi_slaveonly(dip) == DDI_SUCCESS) {
330 mxfe_error(dip, "slot does not support PCI bus-master");
331 return (DDI_FAILURE);
333 /* PCI devices shouldn't generate hilevel interrupts */
334 if (ddi_intr_hilevel(dip, 0) != 0) {
335 mxfe_error(dip, "hilevel interrupts not supported");
336 return (DDI_FAILURE);
338 if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
339 mxfe_error(dip, "unable to setup PCI config handle");
340 return (DDI_FAILURE);
343 venid = pci_config_get16(pci, PCI_VID);
344 devid = pci_config_get16(pci, PCI_DID);
345 revid = pci_config_get16(pci, PCI_RID);
346 svid = pci_config_get16(pci, PCI_SVID);
347 ssid = pci_config_get16(pci, PCI_SSID);
350 * the last entry in the card table matches every possible
351 * card, so the for-loop always terminates properly.
353 cardp = NULL;
354 for (i = 0; i < (sizeof (mxfe_cards) / sizeof (mxfe_card_t)); i++) {
355 if ((venid == mxfe_cards[i].card_venid) &&
356 (devid == mxfe_cards[i].card_devid) &&
357 ((revid & mxfe_cards[i].card_revmask) ==
358 mxfe_cards[i].card_revid)) {
359 cardp = &mxfe_cards[i];
361 if ((svid == mxfe_cards[i].card_venid) &&
362 (ssid == mxfe_cards[i].card_devid) &&
363 ((revid & mxfe_cards[i].card_revmask) ==
364 mxfe_cards[i].card_revid)) {
365 cardp = &mxfe_cards[i];
366 break;
370 if (cardp == NULL) {
371 pci_config_teardown(&pci);
372 mxfe_error(dip, "Unable to identify PCI card");
373 return (DDI_FAILURE);
376 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
377 cardp->card_cardname) != DDI_PROP_SUCCESS) {
378 pci_config_teardown(&pci);
379 mxfe_error(dip, "Unable to create model property");
380 return (DDI_FAILURE);
384 * Grab the PCI cachesize -- we use this to program the
385 * cache-optimization bus access bits.
387 cachesize = pci_config_get8(pci, PCI_CLS);
389 /* this cannot fail */
390 mxfep = kmem_zalloc(sizeof (mxfe_t), KM_SLEEP);
391 ddi_set_driver_private(dip, mxfep);
393 /* get the interrupt block cookie */
394 if (ddi_get_iblock_cookie(dip, 0, &mxfep->mxfe_icookie)
395 != DDI_SUCCESS) {
396 mxfe_error(dip, "ddi_get_iblock_cookie failed");
397 pci_config_teardown(&pci);
398 kmem_free(mxfep, sizeof (mxfe_t));
399 return (DDI_FAILURE);
402 mxfep->mxfe_dip = dip;
403 mxfep->mxfe_cardp = cardp;
404 mxfep->mxfe_phyaddr = -1;
405 mxfep->mxfe_cachesize = cachesize;
407 /* default properties */
408 mxfep->mxfe_adv_aneg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
409 "adv_autoneg_cap", 1);
410 mxfep->mxfe_adv_100T4 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
411 "adv_100T4_cap", 1);
412 mxfep->mxfe_adv_100fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
413 "adv_100fdx_cap", 1);
414 mxfep->mxfe_adv_100hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
415 "adv_100hdx_cap", 1);
416 mxfep->mxfe_adv_10fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
417 "adv_10fdx_cap", 1);
418 mxfep->mxfe_adv_10hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
419 "adv_10hdx_cap", 1);
421 DBG(DPCI, "PCI vendor id = %x", venid);
422 DBG(DPCI, "PCI device id = %x", devid);
423 DBG(DPCI, "PCI revision id = %x", revid);
424 DBG(DPCI, "PCI cachesize = %d", cachesize);
425 DBG(DPCI, "PCI COMM = %x", pci_config_get8(pci, PCI_CMD));
426 DBG(DPCI, "PCI STAT = %x", pci_config_get8(pci, PCI_STAT));
428 mutex_init(&mxfep->mxfe_xmtlock, NULL, MUTEX_DRIVER,
429 mxfep->mxfe_icookie);
430 mutex_init(&mxfep->mxfe_intrlock, NULL, MUTEX_DRIVER,
431 mxfep->mxfe_icookie);
434 * Enable bus master, IO space, and memory space accesses.
436 pci_config_put16(pci, PCI_CMD,
437 pci_config_get16(pci, PCI_CMD) |
438 PCI_CMD_BME | PCI_CMD_MAE | PCI_CMD_MWIE);
440 /* we're done with this now, drop it */
441 pci_config_teardown(&pci);
444 * Initialize interrupt kstat. This should not normally fail, since
445 * we don't use a persistent stat. We do it this way to avoid having
446 * to test for it at run time on the hot path.
448 mxfep->mxfe_intrstat = kstat_create("mxfe", inst, "intr", "controller",
449 KSTAT_TYPE_INTR, 1, 0);
450 if (mxfep->mxfe_intrstat == NULL) {
451 mxfe_error(dip, "kstat_create failed");
452 goto failed;
454 kstat_install(mxfep->mxfe_intrstat);
457 * Map in the device registers.
459 if (ddi_regs_map_setup(dip, 1, (caddr_t *)&mxfep->mxfe_regs,
460 0, 0, &mxfe_devattr, &mxfep->mxfe_regshandle)) {
461 mxfe_error(dip, "ddi_regs_map_setup failed");
462 goto failed;
466 * Allocate DMA resources (descriptor rings and buffers).
468 if ((mxfe_allocrxring(mxfep) != DDI_SUCCESS) ||
469 (mxfe_alloctxring(mxfep) != DDI_SUCCESS)) {
470 mxfe_error(dip, "unable to allocate DMA resources");
471 goto failed;
474 /* Initialize the chip. */
475 mutex_enter(&mxfep->mxfe_intrlock);
476 mutex_enter(&mxfep->mxfe_xmtlock);
477 if (!mxfe_initialize(mxfep)) {
478 mutex_exit(&mxfep->mxfe_xmtlock);
479 mutex_exit(&mxfep->mxfe_intrlock);
480 goto failed;
482 mutex_exit(&mxfep->mxfe_xmtlock);
483 mutex_exit(&mxfep->mxfe_intrlock);
485 /* Determine the number of address bits to our EEPROM. */
486 mxfep->mxfe_sromwidth = mxfe_sromwidth(mxfep);
489 * Get the factory ethernet address. This becomes the current
490 * ethernet address (it can be overridden later via ifconfig).
492 mxfe_getfactaddr(mxfep, mxfep->mxfe_curraddr);
493 mxfep->mxfe_promisc = B_FALSE;
496 * Establish interrupt handler.
498 if (ddi_add_intr(dip, 0, NULL, NULL, mxfe_intr, (caddr_t)mxfep) !=
499 DDI_SUCCESS) {
500 mxfe_error(dip, "unable to add interrupt");
501 goto failed;
504 /* TODO: do the power management stuff */
506 if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
507 mxfe_error(dip, "mac_alloc failed");
508 goto failed;
511 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
512 macp->m_driver = mxfep;
513 macp->m_dip = dip;
514 macp->m_src_addr = mxfep->mxfe_curraddr;
515 macp->m_callbacks = &mxfe_m_callbacks;
516 macp->m_min_sdu = 0;
517 macp->m_max_sdu = ETHERMTU;
518 macp->m_margin = VLAN_TAGSZ;
520 if (mac_register(macp, &mxfep->mxfe_mh) == DDI_SUCCESS) {
521 mac_free(macp);
522 return (DDI_SUCCESS);
525 /* failed to register with MAC */
526 mac_free(macp);
527 failed:
528 if (mxfep->mxfe_icookie != NULL) {
529 ddi_remove_intr(dip, 0, mxfep->mxfe_icookie);
531 if (mxfep->mxfe_intrstat) {
532 kstat_delete(mxfep->mxfe_intrstat);
534 mutex_destroy(&mxfep->mxfe_intrlock);
535 mutex_destroy(&mxfep->mxfe_xmtlock);
537 mxfe_freerxring(mxfep);
538 mxfe_freetxring(mxfep);
540 if (mxfep->mxfe_regshandle != NULL) {
541 ddi_regs_map_free(&mxfep->mxfe_regshandle);
543 kmem_free(mxfep, sizeof (mxfe_t));
544 return (DDI_FAILURE);
548 mxfe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
550 mxfe_t *mxfep;
552 mxfep = ddi_get_driver_private(dip);
553 if (mxfep == NULL) {
554 mxfe_error(dip, "no soft state in detach!");
555 return (DDI_FAILURE);
558 switch (cmd) {
559 case DDI_DETACH:
561 if (mac_unregister(mxfep->mxfe_mh) != 0) {
562 return (DDI_FAILURE);
565 /* make sure hardware is quiesced */
566 mutex_enter(&mxfep->mxfe_intrlock);
567 mutex_enter(&mxfep->mxfe_xmtlock);
568 mxfep->mxfe_flags &= ~MXFE_RUNNING;
569 mxfe_stopall(mxfep);
570 mutex_exit(&mxfep->mxfe_xmtlock);
571 mutex_exit(&mxfep->mxfe_intrlock);
573 /* clean up and shut down device */
574 ddi_remove_intr(dip, 0, mxfep->mxfe_icookie);
576 /* clean up kstats */
577 kstat_delete(mxfep->mxfe_intrstat);
579 ddi_prop_remove_all(dip);
581 /* free up any left over buffers or DMA resources */
582 mxfe_freerxring(mxfep);
583 mxfe_freetxring(mxfep);
585 ddi_regs_map_free(&mxfep->mxfe_regshandle);
586 mutex_destroy(&mxfep->mxfe_intrlock);
587 mutex_destroy(&mxfep->mxfe_xmtlock);
589 kmem_free(mxfep, sizeof (mxfe_t));
590 return (DDI_SUCCESS);
592 case DDI_SUSPEND:
593 /* quiesce the hardware */
594 mutex_enter(&mxfep->mxfe_intrlock);
595 mutex_enter(&mxfep->mxfe_xmtlock);
596 mxfep->mxfe_flags |= MXFE_SUSPENDED;
597 mxfe_stopall(mxfep);
598 mutex_exit(&mxfep->mxfe_xmtlock);
599 mutex_exit(&mxfep->mxfe_intrlock);
600 return (DDI_SUCCESS);
601 default:
602 return (DDI_FAILURE);
607 mxfe_resume(dev_info_t *dip)
609 mxfe_t *mxfep;
611 if ((mxfep = ddi_get_driver_private(dip)) == NULL) {
612 return (DDI_FAILURE);
615 mutex_enter(&mxfep->mxfe_intrlock);
616 mutex_enter(&mxfep->mxfe_xmtlock);
618 mxfep->mxfe_flags &= ~MXFE_SUSPENDED;
620 /* re-initialize chip */
621 if (!mxfe_initialize(mxfep)) {
622 mxfe_error(mxfep->mxfe_dip, "unable to resume chip!");
623 mxfep->mxfe_flags |= MXFE_SUSPENDED;
624 mutex_exit(&mxfep->mxfe_intrlock);
625 mutex_exit(&mxfep->mxfe_xmtlock);
626 return (DDI_SUCCESS);
629 /* start the chip */
630 if (mxfep->mxfe_flags & MXFE_RUNNING) {
631 mxfe_startall(mxfep);
634 /* drop locks */
635 mutex_exit(&mxfep->mxfe_xmtlock);
636 mutex_exit(&mxfep->mxfe_intrlock);
638 return (DDI_SUCCESS);
642 mxfe_quiesce(dev_info_t *dip)
644 mxfe_t *mxfep;
646 if ((mxfep = ddi_get_driver_private(dip)) == NULL) {
647 return (DDI_FAILURE);
650 /* just do a hard reset of everything */
651 SETBIT(mxfep, CSR_PAR, PAR_RESET);
653 return (DDI_SUCCESS);
656 /*ARGSUSED*/
658 mxfe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
660 /* we already receive all multicast frames */
661 return (0);
665 mxfe_m_promisc(void *arg, boolean_t on)
667 mxfe_t *mxfep = arg;
669 /* exclusive access to the card while we reprogram it */
670 mutex_enter(&mxfep->mxfe_intrlock);
671 mutex_enter(&mxfep->mxfe_xmtlock);
672 /* save current promiscuous mode state for replay in resume */
673 mxfep->mxfe_promisc = on;
675 if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) ==
676 MXFE_RUNNING) {
677 if (on)
678 SETBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
679 else
680 CLRBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
683 mutex_exit(&mxfep->mxfe_xmtlock);
684 mutex_exit(&mxfep->mxfe_intrlock);
686 return (0);
690 mxfe_m_unicst(void *arg, const uint8_t *macaddr)
692 mxfe_t *mxfep = arg;
694 mutex_enter(&mxfep->mxfe_intrlock);
695 mutex_enter(&mxfep->mxfe_xmtlock);
696 bcopy(macaddr, mxfep->mxfe_curraddr, ETHERADDRL);
698 mxfe_resetall(mxfep);
700 mutex_exit(&mxfep->mxfe_intrlock);
701 mutex_exit(&mxfep->mxfe_xmtlock);
703 return (0);
706 mblk_t *
707 mxfe_m_tx(void *arg, mblk_t *mp)
709 mxfe_t *mxfep = arg;
710 mblk_t *nmp;
712 mutex_enter(&mxfep->mxfe_xmtlock);
714 if (mxfep->mxfe_flags & MXFE_SUSPENDED) {
715 mutex_exit(&mxfep->mxfe_xmtlock);
716 return (mp);
719 while (mp != NULL) {
720 nmp = mp->b_next;
721 mp->b_next = NULL;
723 if (!mxfe_send(mxfep, mp)) {
724 mp->b_next = nmp;
725 break;
727 mp = nmp;
729 mutex_exit(&mxfep->mxfe_xmtlock);
731 return (mp);
735 * Hardware management.
737 boolean_t
738 mxfe_initialize(mxfe_t *mxfep)
740 int i;
741 unsigned val;
742 uint32_t par, nar;
744 ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
745 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
747 DBG(DCHATTY, "resetting!");
748 SETBIT(mxfep, CSR_PAR, PAR_RESET);
749 for (i = 1; i < 10; i++) {
750 drv_usecwait(5);
751 val = GETCSR(mxfep, CSR_PAR);
752 if (!(val & PAR_RESET)) {
753 break;
756 if (i == 10) {
757 mxfe_error(mxfep->mxfe_dip, "timed out waiting for reset!");
758 return (B_FALSE);
761 /* initialize busctl register */
762 par = PAR_BAR | PAR_MRME | PAR_MRLE | PAR_MWIE;
764 /* set the cache alignment if its supported */
765 switch (mxfep->mxfe_cachesize) {
766 case 8:
767 par |= PAR_CALIGN_8;
768 break;
769 case 16:
770 par |= PAR_CALIGN_16;
771 break;
772 case 32:
773 par |= PAR_CALIGN_32;
774 break;
775 default:
776 par &= ~(PAR_MWIE | PAR_MRME | PAR_MRLE);
779 /* leave the burst length at zero, indicating infinite burst */
780 PUTCSR(mxfep, CSR_PAR, par);
782 mxfe_resetrings(mxfep);
784 /* clear the lost packet counter (cleared on read) */
785 (void) GETCSR(mxfep, CSR_LPC);
787 /* a few other NAR bits */
788 nar = GETCSR(mxfep, CSR_NAR);
789 nar &= ~NAR_RX_HO; /* disable hash only filtering */
790 nar |= NAR_RX_HP; /* hash perfect forwarding */
791 nar |= NAR_RX_MULTI; /* receive all multicast */
792 nar |= NAR_SF; /* store-and-forward */
794 if (mxfep->mxfe_promisc) {
795 nar |= NAR_RX_PROMISC;
796 } else {
797 nar &= ~NAR_RX_PROMISC;
799 PUTCSR(mxfep, CSR_NAR, nar);
801 mxfe_send_setup(mxfep);
803 return (B_TRUE);
807 * Serial EEPROM access - inspired by the FreeBSD implementation.
810 uint8_t
811 mxfe_sromwidth(mxfe_t *mxfep)
813 int i;
814 int eeread;
815 uint8_t addrlen = 8;
817 eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
819 PUTCSR(mxfep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
820 drv_usecwait(1);
821 PUTCSR(mxfep, CSR_SPR, eeread);
823 /* command bits first */
824 for (i = 4; i != 0; i >>= 1) {
825 unsigned val = (SROM_READCMD & i) ? SPR_SROM_DIN : 0;
826 PUTCSR(mxfep, CSR_SPR, eeread | val);
827 drv_usecwait(1);
828 PUTCSR(mxfep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
829 drv_usecwait(1);
832 PUTCSR(mxfep, CSR_SPR, eeread);
834 for (addrlen = 1; addrlen <= 12; addrlen++) {
835 PUTCSR(mxfep, CSR_SPR, eeread | SPR_SROM_CLOCK);
836 drv_usecwait(1);
837 if (!(GETCSR(mxfep, CSR_SPR) & SPR_SROM_DOUT)) {
838 PUTCSR(mxfep, CSR_SPR, eeread);
839 drv_usecwait(1);
840 break;
842 PUTCSR(mxfep, CSR_SPR, eeread);
843 drv_usecwait(1);
846 /* turn off accesses to the EEPROM */
847 PUTCSR(mxfep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
849 DBG(DSROM, "detected srom width = %d bits", addrlen);
851 return ((addrlen < 4 || addrlen > 12) ? 6 : addrlen);
855 * The words in EEPROM are stored in little endian order. We
856 * shift bits out in big endian order, though. This requires
857 * a byte swap on some platforms.
859 uint16_t
860 mxfe_readsromword(mxfe_t *mxfep, unsigned romaddr)
862 int i;
863 uint16_t word = 0;
864 uint16_t retval;
865 int eeread;
866 uint8_t addrlen;
867 int readcmd;
868 uchar_t *ptr;
870 eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
871 addrlen = mxfep->mxfe_sromwidth;
872 readcmd = (SROM_READCMD << addrlen) | romaddr;
874 if (romaddr >= (1 << addrlen)) {
875 /* too big to fit! */
876 return (0);
879 PUTCSR(mxfep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
880 PUTCSR(mxfep, CSR_SPR, eeread);
882 /* command and address bits */
883 for (i = 4 + addrlen; i >= 0; i--) {
884 short val = (readcmd & (1 << i)) ? SPR_SROM_DIN : 0;
885 PUTCSR(mxfep, CSR_SPR, eeread | val);
886 drv_usecwait(1);
887 PUTCSR(mxfep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
888 drv_usecwait(1);
891 PUTCSR(mxfep, CSR_SPR, eeread);
893 for (i = 0; i < 16; i++) {
894 PUTCSR(mxfep, CSR_SPR, eeread | SPR_SROM_CLOCK);
895 drv_usecwait(1);
896 word <<= 1;
897 if (GETCSR(mxfep, CSR_SPR) & SPR_SROM_DOUT) {
898 word |= 1;
900 PUTCSR(mxfep, CSR_SPR, eeread);
901 drv_usecwait(1);
904 /* turn off accesses to the EEPROM */
905 PUTCSR(mxfep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
908 * Fix up the endianness thing. Note that the values
909 * are stored in little endian format on the SROM.
911 DBG(DSROM, "got value %d from SROM (before swap)", word);
912 ptr = (uchar_t *)&word;
913 retval = (ptr[1] << 8) | ptr[0];
914 return (retval);
917 void
918 mxfe_readsrom(mxfe_t *mxfep, unsigned romaddr, unsigned len, void *dest)
920 char *ptr = dest;
921 int i;
922 uint16_t word;
924 for (i = 0; i < len; i++) {
925 word = mxfe_readsromword(mxfep, romaddr + i);
926 bcopy(&word, ptr, 2);
927 ptr += 2;
928 DBG(DSROM, "word at %d is 0x%x", romaddr + i, word);
932 void
933 mxfe_getfactaddr(mxfe_t *mxfep, uchar_t *eaddr)
935 uint16_t word;
936 uchar_t *ptr;
938 /* first read to get the location of mac address in srom */
939 word = mxfe_readsromword(mxfep, SROM_ENADDR / 2);
940 ptr = (uchar_t *)&word;
941 word = (ptr[1] << 8) | ptr[0];
943 /* then read the actual mac address */
944 mxfe_readsrom(mxfep, word / 2, ETHERADDRL / 2, eaddr);
945 DBG(DMACID,
946 "factory ethernet address = %02x:%02x:%02x:%02x:%02x:%02x",
947 eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
950 void
951 mxfe_startphy(mxfe_t *mxfep)
953 switch (MXFE_MODEL(mxfep)) {
954 case MXFE_98713A:
955 mxfe_startphymii(mxfep);
956 break;
957 default:
958 mxfe_startphynway(mxfep);
959 break;
963 void
964 mxfe_stopphy(mxfe_t *mxfep)
966 uint32_t nar;
967 int i;
969 /* stop the phy timer */
970 PUTCSR(mxfep, CSR_TIMER, 0);
972 switch (MXFE_MODEL(mxfep)) {
973 case MXFE_98713A:
974 for (i = 0; i < 32; i++) {
975 mxfe_miiwrite(mxfep, mxfep->mxfe_phyaddr, MII_CONTROL,
976 MII_CONTROL_PWRDN | MII_CONTROL_ISOLATE);
978 break;
979 default:
980 DBG(DPHY, "resetting SIA");
981 PUTCSR(mxfep, CSR_SIA, SIA_RESET);
982 drv_usecwait(500);
983 CLRBIT(mxfep, CSR_TCTL, TCTL_PWR | TCTL_ANE);
984 nar = GETCSR(mxfep, CSR_NAR);
985 nar &= ~(NAR_PORTSEL | NAR_PCS | NAR_SCR | NAR_FDX);
986 nar |= NAR_SPEED;
987 PUTCSR(mxfep, CSR_NAR, nar);
988 break;
992 * mark the link state unknown
994 if (!mxfep->mxfe_resetting) {
995 mxfep->mxfe_linkup = LINK_STATE_UNKNOWN;
996 mxfep->mxfe_ifspeed = 0;
997 mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
998 if (mxfep->mxfe_flags & MXFE_RUNNING)
999 mxfe_reportlink(mxfep);
1004 * NWay support.
1006 void
1007 mxfe_startnway(mxfe_t *mxfep)
1009 unsigned nar;
1010 unsigned tctl;
1011 unsigned restart;
1013 /* this should not happen in a healthy system */
1014 if (mxfep->mxfe_nwaystate != MXFE_NOLINK) {
1015 DBG(DWARN, "link start called out of state (%x)",
1016 mxfep->mxfe_nwaystate);
1017 return;
1020 if (mxfep->mxfe_adv_aneg == 0) {
1021 /* not done for forced mode */
1022 return;
1025 nar = GETCSR(mxfep, CSR_NAR);
1026 restart = nar & (NAR_TX_ENABLE | NAR_RX_ENABLE);
1027 nar &= ~restart;
1029 if (restart != 0)
1030 mxfe_stopmac(mxfep);
1032 nar |= NAR_SCR | NAR_PCS | NAR_HBD;
1033 nar &= ~(NAR_FDX);
1035 tctl = GETCSR(mxfep, CSR_TCTL);
1036 tctl &= ~(TCTL_100FDX | TCTL_100HDX | TCTL_HDX);
1038 if (mxfep->mxfe_adv_100fdx) {
1039 tctl |= TCTL_100FDX;
1041 if (mxfep->mxfe_adv_100hdx) {
1042 tctl |= TCTL_100HDX;
1044 if (mxfep->mxfe_adv_10fdx) {
1045 nar |= NAR_FDX;
1047 if (mxfep->mxfe_adv_10hdx) {
1048 tctl |= TCTL_HDX;
1050 tctl |= TCTL_PWR | TCTL_ANE | TCTL_LTE | TCTL_RSQ;
1052 /* possibly we should add in support for PAUSE frames */
1053 DBG(DPHY, "writing nar = 0x%x", nar);
1054 PUTCSR(mxfep, CSR_NAR, nar);
1056 DBG(DPHY, "writing tctl = 0x%x", tctl);
1057 PUTCSR(mxfep, CSR_TCTL, tctl);
1059 /* restart autonegotation */
1060 DBG(DPHY, "writing tstat = 0x%x", TSTAT_ANS_START);
1061 PUTCSR(mxfep, CSR_TSTAT, TSTAT_ANS_START);
1063 /* restart tx/rx processes... */
1064 if (restart != 0)
1065 mxfe_startmac(mxfep);
1067 /* Macronix initializations from Bolo Tsai */
1068 PUTCSR(mxfep, CSR_MXMAGIC, 0x0b2c0000);
1069 PUTCSR(mxfep, CSR_ACOMP, 0x11000);
1071 mxfep->mxfe_nwaystate = MXFE_NWAYCHECK;
1074 void
1075 mxfe_checklinknway(mxfe_t *mxfep)
1077 unsigned tstat;
1078 uint16_t lpar;
1080 DBG(DPHY, "NWay check, state %x", mxfep->mxfe_nwaystate);
1081 tstat = GETCSR(mxfep, CSR_TSTAT);
1082 lpar = TSTAT_LPAR(tstat);
1084 mxfep->mxfe_anlpar = lpar;
1085 if (tstat & TSTAT_LPN) {
1086 mxfep->mxfe_aner |= MII_AN_EXP_LPCANAN;
1087 } else {
1088 mxfep->mxfe_aner &= ~(MII_AN_EXP_LPCANAN);
1091 DBG(DPHY, "tstat(CSR12) = 0x%x", tstat);
1092 DBG(DPHY, "ANEG state = 0x%x", (tstat & TSTAT_ANS) >> 12);
1094 if ((tstat & TSTAT_ANS) != TSTAT_ANS_OK) {
1095 /* autoneg did not complete */
1096 mxfep->mxfe_bmsr &= ~MII_STATUS_ANDONE;
1097 } else {
1098 mxfep->mxfe_bmsr |= ~MII_STATUS_ANDONE;
1101 if ((tstat & TSTAT_100F) && (tstat & TSTAT_10F)) {
1102 mxfep->mxfe_linkup = LINK_STATE_DOWN;
1103 mxfep->mxfe_ifspeed = 0;
1104 mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1105 mxfep->mxfe_nwaystate = MXFE_NOLINK;
1106 mxfe_reportlink(mxfep);
1107 mxfe_startnway(mxfep);
1108 return;
1112 * if the link is newly up, then we might need to set various
1113 * mode bits, or negotiate for parameters, etc.
1115 if (mxfep->mxfe_adv_aneg) {
1117 uint16_t anlpar;
1119 mxfep->mxfe_linkup = LINK_STATE_UP;
1120 anlpar = mxfep->mxfe_anlpar;
1122 if (tstat & TSTAT_LPN) {
1123 /* partner has NWay */
1125 if ((anlpar & MII_ABILITY_100BASE_TX_FD) &&
1126 mxfep->mxfe_adv_100fdx) {
1127 mxfep->mxfe_ifspeed = 100000000;
1128 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1129 } else if ((anlpar & MII_ABILITY_100BASE_TX) &&
1130 mxfep->mxfe_adv_100hdx) {
1131 mxfep->mxfe_ifspeed = 100000000;
1132 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1133 } else if ((anlpar & MII_ABILITY_10BASE_T_FD) &&
1134 mxfep->mxfe_adv_10fdx) {
1135 mxfep->mxfe_ifspeed = 10000000;
1136 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1137 } else if ((anlpar & MII_ABILITY_10BASE_T) &&
1138 mxfep->mxfe_adv_10hdx) {
1139 mxfep->mxfe_ifspeed = 10000000;
1140 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1141 } else {
1142 mxfep->mxfe_ifspeed = 0;
1144 } else {
1145 /* link partner does not have NWay */
1146 /* just assume half duplex, since we can't detect */
1147 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1148 if (!(tstat & TSTAT_100F)) {
1149 DBG(DPHY, "Partner doesn't have NWAY");
1150 mxfep->mxfe_ifspeed = 100000000;
1151 } else {
1152 mxfep->mxfe_ifspeed = 10000000;
1155 } else {
1156 /* forced modes */
1157 mxfep->mxfe_linkup = LINK_STATE_UP;
1158 if (mxfep->mxfe_adv_100fdx) {
1159 mxfep->mxfe_ifspeed = 100000000;
1160 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1161 } else if (mxfep->mxfe_adv_100hdx) {
1162 mxfep->mxfe_ifspeed = 100000000;
1163 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1164 } else if (mxfep->mxfe_adv_10fdx) {
1165 mxfep->mxfe_ifspeed = 10000000;
1166 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1167 } else if (mxfep->mxfe_adv_10hdx) {
1168 mxfep->mxfe_ifspeed = 10000000;
1169 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1170 } else {
1171 mxfep->mxfe_ifspeed = 0;
1174 mxfe_reportlink(mxfep);
1175 mxfep->mxfe_nwaystate = MXFE_GOODLINK;
1178 void
1179 mxfe_startphynway(mxfe_t *mxfep)
1181 /* take NWay and PHY out of reset */
1182 PUTCSR(mxfep, CSR_SIA, SIA_NRESET);
1183 drv_usecwait(500);
1185 mxfep->mxfe_nwaystate = MXFE_NOLINK;
1186 mxfep->mxfe_bmsr = MII_STATUS_CANAUTONEG |
1187 MII_STATUS_100_BASEX_FD | MII_STATUS_100_BASEX |
1188 MII_STATUS_10_FD | MII_STATUS_10;
1189 mxfep->mxfe_cap_aneg =
1190 mxfep->mxfe_cap_100fdx = mxfep->mxfe_cap_100hdx =
1191 mxfep->mxfe_cap_10fdx = mxfep->mxfe_cap_10hdx = 1;
1193 /* lie about the transceiver... its not really 802.3u compliant */
1194 mxfep->mxfe_phyaddr = 0;
1195 mxfep->mxfe_phyinuse = XCVR_100X;
1196 mxfep->mxfe_phyid = 0;
1198 /* 100-T4 not supported with NWay */
1199 mxfep->mxfe_adv_100T4 = 0;
1200 mxfep->mxfe_cap_100T4 = 0;
1202 /* make sure at least one valid mode is selected */
1203 if ((!mxfep->mxfe_adv_100fdx) &&
1204 (!mxfep->mxfe_adv_100hdx) &&
1205 (!mxfep->mxfe_adv_10fdx) &&
1206 (!mxfep->mxfe_adv_10hdx)) {
1207 mxfe_error(mxfep->mxfe_dip, "No valid link mode selected.");
1208 mxfe_error(mxfep->mxfe_dip, "Powering down PHY.");
1209 mxfe_stopphy(mxfep);
1210 mxfep->mxfe_linkup = LINK_STATE_DOWN;
1211 if (mxfep->mxfe_flags & MXFE_RUNNING)
1212 mxfe_reportlink(mxfep);
1213 return;
1216 if (mxfep->mxfe_adv_aneg == 0) {
1217 /* forced mode */
1218 unsigned nar;
1219 unsigned tctl;
1221 nar = GETCSR(mxfep, CSR_NAR);
1222 tctl = GETCSR(mxfep, CSR_TCTL);
1224 ASSERT((nar & (NAR_TX_ENABLE | NAR_RX_ENABLE)) == 0);
1226 nar &= ~(NAR_FDX | NAR_PORTSEL | NAR_SCR | NAR_SPEED);
1227 tctl &= ~TCTL_ANE;
1228 if (mxfep->mxfe_adv_100fdx) {
1229 nar |= NAR_PORTSEL | NAR_PCS | NAR_SCR | NAR_FDX;
1230 } else if (mxfep->mxfe_adv_100hdx) {
1231 nar |= NAR_PORTSEL | NAR_PCS | NAR_SCR;
1232 } else if (mxfep->mxfe_adv_10fdx) {
1233 nar |= NAR_FDX | NAR_SPEED;
1234 } else { /* mxfep->mxfe_adv_10hdx */
1235 nar |= NAR_SPEED;
1238 PUTCSR(mxfep, CSR_NAR, nar);
1239 PUTCSR(mxfep, CSR_TCTL, tctl);
1241 /* Macronix initializations from Bolo Tsai */
1242 PUTCSR(mxfep, CSR_MXMAGIC, 0x0b2c0000);
1243 PUTCSR(mxfep, CSR_ACOMP, 0x11000);
1244 } else {
1245 mxfe_startnway(mxfep);
1247 PUTCSR(mxfep, CSR_TIMER, TIMER_LOOP |
1248 (MXFE_LINKTIMER * 1000 / TIMER_USEC));
1252 * MII management.
1254 void
1255 mxfe_startphymii(mxfe_t *mxfep)
1257 unsigned phyaddr;
1258 unsigned bmcr;
1259 unsigned bmsr;
1260 unsigned anar;
1261 unsigned phyidr1;
1262 unsigned phyidr2;
1263 int retries;
1264 int cnt;
1266 mxfep->mxfe_phyaddr = -1;
1268 /* search for first PHY we can find */
1269 for (phyaddr = 0; phyaddr < 32; phyaddr++) {
1270 bmsr = mxfe_miiread(mxfep, phyaddr, MII_STATUS);
1271 if ((bmsr != 0) && (bmsr != 0xffff)) {
1272 mxfep->mxfe_phyaddr = phyaddr;
1273 break;
1277 phyidr1 = mxfe_miiread(mxfep, phyaddr, MII_PHYIDH);
1278 phyidr2 = mxfe_miiread(mxfep, phyaddr, MII_PHYIDL);
1279 mxfep->mxfe_phyid = (phyidr1 << 16) | (phyidr2);
1282 * Generally, all Macronix based devices use an internal
1283 * 100BASE-TX internal transceiver. If we ever run into a
1284 * variation on this, then the following logic will need to be
1285 * enhanced.
1287 * One could question the value of the XCVR_INUSE field in the
1288 * MII statistics.
1290 if (bmsr & MII_STATUS_100_BASE_T4) {
1291 mxfep->mxfe_phyinuse = XCVR_100T4;
1292 } else {
1293 mxfep->mxfe_phyinuse = XCVR_100X;
1296 /* assume we support everything to start */
1297 mxfep->mxfe_cap_aneg = mxfep->mxfe_cap_100T4 =
1298 mxfep->mxfe_cap_100fdx = mxfep->mxfe_cap_100hdx =
1299 mxfep->mxfe_cap_10fdx = mxfep->mxfe_cap_10hdx = 1;
1301 DBG(DPHY, "phy at %d: %x,%x", phyaddr, phyidr1, phyidr2);
1302 DBG(DPHY, "bmsr = %x", mxfe_miiread(mxfep,
1303 mxfep->mxfe_phyaddr, MII_STATUS));
1304 DBG(DPHY, "anar = %x", mxfe_miiread(mxfep,
1305 mxfep->mxfe_phyaddr, MII_AN_ADVERT));
1306 DBG(DPHY, "anlpar = %x", mxfe_miiread(mxfep,
1307 mxfep->mxfe_phyaddr, MII_AN_LPABLE));
1308 DBG(DPHY, "aner = %x", mxfe_miiread(mxfep,
1309 mxfep->mxfe_phyaddr, MII_AN_EXPANSION));
1311 DBG(DPHY, "resetting phy");
1313 /* we reset the phy block */
1314 mxfe_miiwrite(mxfep, phyaddr, MII_CONTROL, MII_CONTROL_RESET);
1316 * wait for it to complete -- 500usec is still to short to
1317 * bother getting the system clock involved.
1319 drv_usecwait(500);
1320 for (retries = 0; retries < 10; retries++) {
1321 if (mxfe_miiread(mxfep, phyaddr, MII_CONTROL) &
1322 MII_CONTROL_RESET) {
1323 drv_usecwait(500);
1324 continue;
1326 break;
1328 if (retries == 100) {
1329 mxfe_error(mxfep->mxfe_dip, "timeout waiting on phy to reset");
1330 return;
1333 DBG(DPHY, "phy reset complete");
1335 bmsr = mxfe_miiread(mxfep, phyaddr, MII_STATUS);
1336 bmcr = mxfe_miiread(mxfep, phyaddr, MII_CONTROL);
1337 anar = mxfe_miiread(mxfep, phyaddr, MII_AN_ADVERT);
1339 anar &= ~(MII_ABILITY_100BASE_T4 |
1340 MII_ABILITY_100BASE_TX_FD | MII_ABILITY_100BASE_TX |
1341 MII_ABILITY_10BASE_T_FD | MII_ABILITY_10BASE_T);
1343 /* disable modes not supported in hardware */
1344 if (!(bmsr & MII_STATUS_100_BASE_T4)) {
1345 mxfep->mxfe_adv_100T4 = 0;
1346 mxfep->mxfe_cap_100T4 = 0;
1348 if (!(bmsr & MII_STATUS_100_BASEX_FD)) {
1349 mxfep->mxfe_adv_100fdx = 0;
1350 mxfep->mxfe_cap_100fdx = 0;
1352 if (!(bmsr & MII_STATUS_100_BASEX)) {
1353 mxfep->mxfe_adv_100hdx = 0;
1354 mxfep->mxfe_cap_100hdx = 0;
1356 if (!(bmsr & MII_STATUS_10_FD)) {
1357 mxfep->mxfe_adv_10fdx = 0;
1358 mxfep->mxfe_cap_10fdx = 0;
1360 if (!(bmsr & MII_STATUS_10)) {
1361 mxfep->mxfe_adv_10hdx = 0;
1362 mxfep->mxfe_cap_10hdx = 0;
1364 if (!(bmsr & MII_STATUS_CANAUTONEG)) {
1365 mxfep->mxfe_adv_aneg = 0;
1366 mxfep->mxfe_cap_aneg = 0;
1369 cnt = 0;
1370 if (mxfep->mxfe_adv_100T4) {
1371 anar |= MII_ABILITY_100BASE_T4;
1372 cnt++;
1374 if (mxfep->mxfe_adv_100fdx) {
1375 anar |= MII_ABILITY_100BASE_TX_FD;
1376 cnt++;
1378 if (mxfep->mxfe_adv_100hdx) {
1379 anar |= MII_ABILITY_100BASE_TX;
1380 cnt++;
1382 if (mxfep->mxfe_adv_10fdx) {
1383 anar |= MII_ABILITY_10BASE_T_FD;
1384 cnt++;
1386 if (mxfep->mxfe_adv_10hdx) {
1387 anar |= MII_ABILITY_10BASE_T;
1388 cnt++;
1392 * Make certain at least one valid link mode is selected.
1394 if (!cnt) {
1395 mxfe_error(mxfep->mxfe_dip, "No valid link mode selected.");
1396 mxfe_error(mxfep->mxfe_dip, "Powering down PHY.");
1397 mxfe_stopphy(mxfep);
1398 mxfep->mxfe_linkup = LINK_STATE_DOWN;
1399 if (mxfep->mxfe_flags & MXFE_RUNNING)
1400 mxfe_reportlink(mxfep);
1401 return;
1404 if ((mxfep->mxfe_adv_aneg) && (bmsr & MII_STATUS_CANAUTONEG)) {
1405 DBG(DPHY, "using autoneg mode");
1406 bmcr = (MII_CONTROL_ANE | MII_CONTROL_RSAN);
1407 } else {
1408 DBG(DPHY, "using forced mode");
1409 if (mxfep->mxfe_adv_100fdx) {
1410 bmcr = (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX);
1411 } else if (mxfep->mxfe_adv_100hdx) {
1412 bmcr = MII_CONTROL_100MB;
1413 } else if (mxfep->mxfe_adv_10fdx) {
1414 bmcr = MII_CONTROL_FDUPLEX;
1415 } else {
1416 /* 10HDX */
1417 bmcr = 0;
1421 DBG(DPHY, "programming anar to 0x%x", anar);
1422 mxfe_miiwrite(mxfep, phyaddr, MII_AN_ADVERT, anar);
1423 DBG(DPHY, "programming bmcr to 0x%x", bmcr);
1424 mxfe_miiwrite(mxfep, phyaddr, MII_CONTROL, bmcr);
1427 * schedule a query of the link status
1429 PUTCSR(mxfep, CSR_TIMER, TIMER_LOOP |
1430 (MXFE_LINKTIMER * 1000 / TIMER_USEC));
1433 void
1434 mxfe_reportlink(mxfe_t *mxfep)
1436 int changed = 0;
1438 if (mxfep->mxfe_ifspeed != mxfep->mxfe_lastifspeed) {
1439 mxfep->mxfe_lastifspeed = mxfep->mxfe_ifspeed;
1440 changed++;
1442 if (mxfep->mxfe_duplex != mxfep->mxfe_lastduplex) {
1443 mxfep->mxfe_lastduplex = mxfep->mxfe_duplex;
1444 changed++;
1446 if (mxfep->mxfe_linkup != mxfep->mxfe_lastlinkup) {
1447 mxfep->mxfe_lastlinkup = mxfep->mxfe_linkup;
1448 changed++;
1450 if (changed)
1451 mac_link_update(mxfep->mxfe_mh, mxfep->mxfe_linkup);
1454 void
1455 mxfe_checklink(mxfe_t *mxfep)
1457 if ((mxfep->mxfe_flags & MXFE_RUNNING) == 0)
1458 return;
1460 if ((mxfep->mxfe_txstall_time != 0) &&
1461 (gethrtime() > mxfep->mxfe_txstall_time) &&
1462 (mxfep->mxfe_txavail != MXFE_TXRING)) {
1463 mxfep->mxfe_txstall_time = 0;
1464 mxfe_error(mxfep->mxfe_dip, "TX stall detected!");
1465 mxfe_resetall(mxfep);
1466 return;
1469 switch (MXFE_MODEL(mxfep)) {
1470 case MXFE_98713A:
1471 mxfe_checklinkmii(mxfep);
1472 break;
1473 default:
1474 mxfe_checklinknway(mxfep);
1478 void
1479 mxfe_checklinkmii(mxfe_t *mxfep)
1481 /* read MII state registers */
1482 uint16_t bmsr;
1483 uint16_t bmcr;
1484 uint16_t anar;
1485 uint16_t anlpar;
1486 uint16_t aner;
1488 /* read this twice, to clear latched link state */
1489 bmsr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_STATUS);
1490 bmsr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_STATUS);
1491 bmcr = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_CONTROL);
1492 anar = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_ADVERT);
1493 anlpar = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_LPABLE);
1494 aner = mxfe_miiread(mxfep, mxfep->mxfe_phyaddr, MII_AN_EXPANSION);
1496 mxfep->mxfe_bmsr = bmsr;
1497 mxfep->mxfe_anlpar = anlpar;
1498 mxfep->mxfe_aner = aner;
1500 if (bmsr & MII_STATUS_REMFAULT) {
1501 mxfe_error(mxfep->mxfe_dip, "Remote fault detected.");
1503 if (bmsr & MII_STATUS_JABBERING) {
1504 mxfe_error(mxfep->mxfe_dip, "Jabber condition detected.");
1506 if ((bmsr & MII_STATUS_LINKUP) == 0) {
1507 /* no link */
1508 mxfep->mxfe_ifspeed = 0;
1509 mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1510 mxfep->mxfe_linkup = LINK_STATE_DOWN;
1511 mxfe_reportlink(mxfep);
1512 return;
1515 DBG(DCHATTY, "link up!");
1516 mxfep->mxfe_linkup = LINK_STATE_UP;
1518 if (!(bmcr & MII_CONTROL_ANE)) {
1519 /* forced mode */
1520 if (bmcr & MII_CONTROL_100MB) {
1521 mxfep->mxfe_ifspeed = 100000000;
1522 } else {
1523 mxfep->mxfe_ifspeed = 10000000;
1525 if (bmcr & MII_CONTROL_FDUPLEX) {
1526 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1527 } else {
1528 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1530 } else if ((!(bmsr & MII_STATUS_CANAUTONEG)) ||
1531 (!(bmsr & MII_STATUS_ANDONE))) {
1532 mxfep->mxfe_ifspeed = 0;
1533 mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1534 } else if (anar & anlpar & MII_ABILITY_100BASE_TX_FD) {
1535 mxfep->mxfe_ifspeed = 100000000;
1536 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1537 } else if (anar & anlpar & MII_ABILITY_100BASE_T4) {
1538 mxfep->mxfe_ifspeed = 100000000;
1539 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1540 } else if (anar & anlpar & MII_ABILITY_100BASE_TX) {
1541 mxfep->mxfe_ifspeed = 100000000;
1542 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1543 } else if (anar & anlpar & MII_ABILITY_10BASE_T_FD) {
1544 mxfep->mxfe_ifspeed = 10000000;
1545 mxfep->mxfe_duplex = LINK_DUPLEX_FULL;
1546 } else if (anar & anlpar & MII_ABILITY_10BASE_T) {
1547 mxfep->mxfe_ifspeed = 10000000;
1548 mxfep->mxfe_duplex = LINK_DUPLEX_HALF;
1549 } else {
1550 mxfep->mxfe_ifspeed = 0;
1551 mxfep->mxfe_duplex = LINK_DUPLEX_UNKNOWN;
1554 mxfe_reportlink(mxfep);
1557 void
1558 mxfe_miitristate(mxfe_t *mxfep)
1560 unsigned val = SPR_SROM_WRITE | SPR_MII_CTRL;
1561 PUTCSR(mxfep, CSR_SPR, val);
1562 drv_usecwait(1);
1563 PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1564 drv_usecwait(1);
1567 void
1568 mxfe_miiwritebit(mxfe_t *mxfep, uint8_t bit)
1570 unsigned val = bit ? SPR_MII_DOUT : 0;
1571 PUTCSR(mxfep, CSR_SPR, val);
1572 drv_usecwait(1);
1573 PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1574 drv_usecwait(1);
1577 uint8_t
1578 mxfe_miireadbit(mxfe_t *mxfep)
1580 unsigned val = SPR_MII_CTRL | SPR_SROM_READ;
1581 uint8_t bit;
1582 PUTCSR(mxfep, CSR_SPR, val);
1583 drv_usecwait(1);
1584 bit = (GETCSR(mxfep, CSR_SPR) & SPR_MII_DIN) ? 1 : 0;
1585 PUTCSR(mxfep, CSR_SPR, val | SPR_MII_CLOCK);
1586 drv_usecwait(1);
1587 return (bit);
1590 uint16_t
1591 mxfe_miiread(mxfe_t *mxfep, int phy, int reg)
1593 switch (MXFE_MODEL(mxfep)) {
1594 case MXFE_98713A:
1595 return (mxfe_miiread98713(mxfep, phy, reg));
1596 default:
1597 return (0xffff);
1601 uint16_t
1602 mxfe_miireadgeneral(mxfe_t *mxfep, int phy, int reg)
1604 uint16_t value = 0;
1605 int i;
1607 /* send the 32 bit preamble */
1608 for (i = 0; i < 32; i++) {
1609 mxfe_miiwritebit(mxfep, 1);
1612 /* send the start code - 01b */
1613 mxfe_miiwritebit(mxfep, 0);
1614 mxfe_miiwritebit(mxfep, 1);
1616 /* send the opcode for read, - 10b */
1617 mxfe_miiwritebit(mxfep, 1);
1618 mxfe_miiwritebit(mxfep, 0);
1620 /* next we send the 5 bit phy address */
1621 for (i = 0x10; i > 0; i >>= 1) {
1622 mxfe_miiwritebit(mxfep, (phy & i) ? 1 : 0);
1625 /* the 5 bit register address goes next */
1626 for (i = 0x10; i > 0; i >>= 1) {
1627 mxfe_miiwritebit(mxfep, (reg & i) ? 1 : 0);
1630 /* turnaround - tristate followed by logic 0 */
1631 mxfe_miitristate(mxfep);
1632 mxfe_miiwritebit(mxfep, 0);
1634 /* read the 16 bit register value */
1635 for (i = 0x8000; i > 0; i >>= 1) {
1636 value <<= 1;
1637 value |= mxfe_miireadbit(mxfep);
1639 mxfe_miitristate(mxfep);
1640 return (value);
1643 uint16_t
1644 mxfe_miiread98713(mxfe_t *mxfep, int phy, int reg)
1646 unsigned nar;
1647 uint16_t retval;
1649 * like an ordinary MII, but we have to turn off portsel while
1650 * we read it.
1652 nar = GETCSR(mxfep, CSR_NAR);
1653 PUTCSR(mxfep, CSR_NAR, nar & ~NAR_PORTSEL);
1654 retval = mxfe_miireadgeneral(mxfep, phy, reg);
1655 PUTCSR(mxfep, CSR_NAR, nar);
1656 return (retval);
1659 void
1660 mxfe_miiwrite(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1662 switch (MXFE_MODEL(mxfep)) {
1663 case MXFE_98713A:
1664 mxfe_miiwrite98713(mxfep, phy, reg, val);
1665 break;
1666 default:
1667 break;
1671 void
1672 mxfe_miiwritegeneral(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1674 int i;
1676 /* send the 32 bit preamble */
1677 for (i = 0; i < 32; i++) {
1678 mxfe_miiwritebit(mxfep, 1);
1681 /* send the start code - 01b */
1682 mxfe_miiwritebit(mxfep, 0);
1683 mxfe_miiwritebit(mxfep, 1);
1685 /* send the opcode for write, - 01b */
1686 mxfe_miiwritebit(mxfep, 0);
1687 mxfe_miiwritebit(mxfep, 1);
1689 /* next we send the 5 bit phy address */
1690 for (i = 0x10; i > 0; i >>= 1) {
1691 mxfe_miiwritebit(mxfep, (phy & i) ? 1 : 0);
1694 /* the 5 bit register address goes next */
1695 for (i = 0x10; i > 0; i >>= 1) {
1696 mxfe_miiwritebit(mxfep, (reg & i) ? 1 : 0);
1699 /* turnaround - tristate followed by logic 0 */
1700 mxfe_miitristate(mxfep);
1701 mxfe_miiwritebit(mxfep, 0);
1703 /* now write out our data (16 bits) */
1704 for (i = 0x8000; i > 0; i >>= 1) {
1705 mxfe_miiwritebit(mxfep, (val & i) ? 1 : 0);
1708 /* idle mode */
1709 mxfe_miitristate(mxfep);
1712 void
1713 mxfe_miiwrite98713(mxfe_t *mxfep, int phy, int reg, uint16_t val)
1715 unsigned nar;
1717 * like an ordinary MII, but we have to turn off portsel while
1718 * we read it.
1720 nar = GETCSR(mxfep, CSR_NAR);
1721 PUTCSR(mxfep, CSR_NAR, nar & ~NAR_PORTSEL);
1722 mxfe_miiwritegeneral(mxfep, phy, reg, val);
1723 PUTCSR(mxfep, CSR_NAR, nar);
1727 mxfe_m_start(void *arg)
1729 mxfe_t *mxfep = arg;
1731 /* grab exclusive access to the card */
1732 mutex_enter(&mxfep->mxfe_intrlock);
1733 mutex_enter(&mxfep->mxfe_xmtlock);
1735 mxfe_startall(mxfep);
1736 mxfep->mxfe_flags |= MXFE_RUNNING;
1738 mutex_exit(&mxfep->mxfe_xmtlock);
1739 mutex_exit(&mxfep->mxfe_intrlock);
1740 return (0);
1743 void
1744 mxfe_m_stop(void *arg)
1746 mxfe_t *mxfep = arg;
1748 /* exclusive access to the hardware! */
1749 mutex_enter(&mxfep->mxfe_intrlock);
1750 mutex_enter(&mxfep->mxfe_xmtlock);
1752 mxfe_stopall(mxfep);
1753 mxfep->mxfe_flags &= ~MXFE_RUNNING;
1755 mutex_exit(&mxfep->mxfe_xmtlock);
1756 mutex_exit(&mxfep->mxfe_intrlock);
1759 void
1760 mxfe_startmac(mxfe_t *mxfep)
1762 /* verify exclusive access to the card */
1763 ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1764 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1766 /* start the card */
1767 SETBIT(mxfep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1769 if (mxfep->mxfe_txavail != MXFE_TXRING)
1770 PUTCSR(mxfep, CSR_TDR, 0);
1772 /* tell the mac that we are ready to go! */
1773 if (mxfep->mxfe_flags & MXFE_RUNNING)
1774 mac_tx_update(mxfep->mxfe_mh);
1777 void
1778 mxfe_stopmac(mxfe_t *mxfep)
1780 int i;
1782 /* exclusive access to the hardware! */
1783 ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1784 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1786 CLRBIT(mxfep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1789 * A 1518 byte frame at 10Mbps takes about 1.2 msec to drain.
1790 * We just add up to the nearest msec (2), which should be
1791 * plenty to complete.
1793 * Note that some chips never seem to indicate the transition to
1794 * the stopped state properly. Experience shows that we can safely
1795 * proceed anyway, after waiting the requisite timeout.
1797 for (i = 2000; i != 0; i -= 10) {
1798 if ((GETCSR(mxfep, CSR_SR) & (SR_TX_STATE | SR_RX_STATE)) == 0)
1799 break;
1800 drv_usecwait(10);
1803 /* prevent an interrupt */
1804 PUTCSR(mxfep, CSR_SR, INT_RXSTOPPED | INT_TXSTOPPED);
1807 void
1808 mxfe_resetrings(mxfe_t *mxfep)
1810 int i;
1812 /* now we need to reset the pointers... */
1813 PUTCSR(mxfep, CSR_RDB, 0);
1814 PUTCSR(mxfep, CSR_TDB, 0);
1816 /* reset the descriptor ring pointers */
1817 mxfep->mxfe_rxhead = 0;
1818 mxfep->mxfe_txreclaim = 0;
1819 mxfep->mxfe_txsend = 0;
1820 mxfep->mxfe_txavail = MXFE_TXRING;
1822 /* set up transmit descriptor ring */
1823 for (i = 0; i < MXFE_TXRING; i++) {
1824 mxfe_desc_t *tmdp = &mxfep->mxfe_txdescp[i];
1825 unsigned control = 0;
1826 if (i == (MXFE_TXRING - 1)) {
1827 control |= TXCTL_ENDRING;
1829 PUTTXDESC(mxfep, tmdp->desc_status, 0);
1830 PUTTXDESC(mxfep, tmdp->desc_control, control);
1831 PUTTXDESC(mxfep, tmdp->desc_buffer1, 0);
1832 PUTTXDESC(mxfep, tmdp->desc_buffer2, 0);
1833 SYNCTXDESC(mxfep, i, DDI_DMA_SYNC_FORDEV);
1835 PUTCSR(mxfep, CSR_TDB, mxfep->mxfe_txdesc_paddr);
1837 /* make the receive buffers available */
1838 for (i = 0; i < MXFE_RXRING; i++) {
1839 mxfe_rxbuf_t *rxb = mxfep->mxfe_rxbufs[i];
1840 mxfe_desc_t *rmdp = &mxfep->mxfe_rxdescp[i];
1841 unsigned control;
1843 control = MXFE_BUFSZ & RXCTL_BUFLEN1;
1844 if (i == (MXFE_RXRING - 1)) {
1845 control |= RXCTL_ENDRING;
1847 PUTRXDESC(mxfep, rmdp->desc_buffer1, rxb->rxb_paddr);
1848 PUTRXDESC(mxfep, rmdp->desc_buffer2, 0);
1849 PUTRXDESC(mxfep, rmdp->desc_control, control);
1850 PUTRXDESC(mxfep, rmdp->desc_status, RXSTAT_OWN);
1851 SYNCRXDESC(mxfep, i, DDI_DMA_SYNC_FORDEV);
1853 PUTCSR(mxfep, CSR_RDB, mxfep->mxfe_rxdesc_paddr);
1856 void
1857 mxfe_stopall(mxfe_t *mxfep)
1859 mxfe_disableinterrupts(mxfep);
1861 mxfe_stopmac(mxfep);
1863 /* stop the phy */
1864 mxfe_stopphy(mxfep);
1867 void
1868 mxfe_startall(mxfe_t *mxfep)
1870 ASSERT(mutex_owned(&mxfep->mxfe_intrlock));
1871 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
1873 /* make sure interrupts are disabled to begin */
1874 mxfe_disableinterrupts(mxfep);
1876 /* initialize the chip */
1877 (void) mxfe_initialize(mxfep);
1879 /* now we can enable interrupts */
1880 mxfe_enableinterrupts(mxfep);
1882 /* start up the phy */
1883 mxfe_startphy(mxfep);
1885 /* start up the mac */
1886 mxfe_startmac(mxfep);
1889 void
1890 mxfe_resetall(mxfe_t *mxfep)
1892 mxfep->mxfe_resetting = B_TRUE;
1893 mxfe_stopall(mxfep);
1894 mxfep->mxfe_resetting = B_FALSE;
1895 mxfe_startall(mxfep);
1898 mxfe_txbuf_t *
1899 mxfe_alloctxbuf(mxfe_t *mxfep)
1901 ddi_dma_cookie_t dmac;
1902 unsigned ncookies;
1903 mxfe_txbuf_t *txb;
1904 size_t len;
1906 txb = kmem_zalloc(sizeof (*txb), KM_SLEEP);
1908 if (ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_txattr,
1909 DDI_DMA_SLEEP, NULL, &txb->txb_dmah) != DDI_SUCCESS) {
1910 return (NULL);
1913 if (ddi_dma_mem_alloc(txb->txb_dmah, MXFE_BUFSZ, &mxfe_bufattr,
1914 DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &txb->txb_buf,
1915 &len, &txb->txb_acch) != DDI_SUCCESS) {
1916 return (NULL);
1918 if (ddi_dma_addr_bind_handle(txb->txb_dmah, NULL, txb->txb_buf,
1919 len, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1920 &dmac, &ncookies) != DDI_DMA_MAPPED) {
1921 return (NULL);
1923 txb->txb_paddr = dmac.dmac_address;
1925 return (txb);
1928 void
1929 mxfe_destroytxbuf(mxfe_txbuf_t *txb)
1931 if (txb != NULL) {
1932 if (txb->txb_paddr)
1933 (void) ddi_dma_unbind_handle(txb->txb_dmah);
1934 if (txb->txb_acch)
1935 ddi_dma_mem_free(&txb->txb_acch);
1936 if (txb->txb_dmah)
1937 ddi_dma_free_handle(&txb->txb_dmah);
1938 kmem_free(txb, sizeof (*txb));
1942 mxfe_rxbuf_t *
1943 mxfe_allocrxbuf(mxfe_t *mxfep)
1945 mxfe_rxbuf_t *rxb;
1946 size_t len;
1947 unsigned ccnt;
1948 ddi_dma_cookie_t dmac;
1950 rxb = kmem_zalloc(sizeof (*rxb), KM_SLEEP);
1952 if (ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
1953 DDI_DMA_SLEEP, NULL, &rxb->rxb_dmah) != DDI_SUCCESS) {
1954 kmem_free(rxb, sizeof (*rxb));
1955 return (NULL);
1957 if (ddi_dma_mem_alloc(rxb->rxb_dmah, MXFE_BUFSZ, &mxfe_bufattr,
1958 DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1959 &rxb->rxb_buf, &len, &rxb->rxb_acch) != DDI_SUCCESS) {
1960 ddi_dma_free_handle(&rxb->rxb_dmah);
1961 kmem_free(rxb, sizeof (*rxb));
1962 return (NULL);
1964 if (ddi_dma_addr_bind_handle(rxb->rxb_dmah, NULL, rxb->rxb_buf, len,
1965 DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dmac,
1966 &ccnt) != DDI_DMA_MAPPED) {
1967 ddi_dma_mem_free(&rxb->rxb_acch);
1968 ddi_dma_free_handle(&rxb->rxb_dmah);
1969 kmem_free(rxb, sizeof (*rxb));
1970 return (NULL);
1972 rxb->rxb_paddr = dmac.dmac_address;
1974 return (rxb);
1977 void
1978 mxfe_destroyrxbuf(mxfe_rxbuf_t *rxb)
1980 if (rxb != NULL) {
1981 (void) ddi_dma_unbind_handle(rxb->rxb_dmah);
1982 ddi_dma_mem_free(&rxb->rxb_acch);
1983 ddi_dma_free_handle(&rxb->rxb_dmah);
1984 kmem_free(rxb, sizeof (*rxb));
1989 * Allocate receive resources.
1992 mxfe_allocrxring(mxfe_t *mxfep)
1994 int rval;
1995 int i;
1996 size_t size;
1997 size_t len;
1998 ddi_dma_cookie_t dmac;
1999 unsigned ncookies;
2000 caddr_t kaddr;
2002 size = MXFE_RXRING * sizeof (mxfe_desc_t);
2004 rval = ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
2005 DDI_DMA_SLEEP, NULL, &mxfep->mxfe_rxdesc_dmah);
2006 if (rval != DDI_SUCCESS) {
2007 mxfe_error(mxfep->mxfe_dip,
2008 "unable to allocate DMA handle for rx descriptors");
2009 return (DDI_FAILURE);
2012 rval = ddi_dma_mem_alloc(mxfep->mxfe_rxdesc_dmah, size, &mxfe_devattr,
2013 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
2014 &mxfep->mxfe_rxdesc_acch);
2015 if (rval != DDI_SUCCESS) {
2016 mxfe_error(mxfep->mxfe_dip,
2017 "unable to allocate DMA memory for rx descriptors");
2018 return (DDI_FAILURE);
2021 rval = ddi_dma_addr_bind_handle(mxfep->mxfe_rxdesc_dmah, NULL, kaddr,
2022 size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
2023 &dmac, &ncookies);
2024 if (rval != DDI_DMA_MAPPED) {
2025 mxfe_error(mxfep->mxfe_dip,
2026 "unable to bind DMA for rx descriptors");
2027 return (DDI_FAILURE);
2030 /* because of mxfe_dma_attr */
2031 ASSERT(ncookies == 1);
2033 /* we take the 32-bit physical address out of the cookie */
2034 mxfep->mxfe_rxdesc_paddr = dmac.dmac_address;
2035 mxfep->mxfe_rxdescp = (void *)kaddr;
2037 /* allocate buffer pointers (not the buffers themselves, yet) */
2038 mxfep->mxfe_rxbufs = kmem_zalloc(MXFE_RXRING * sizeof (mxfe_rxbuf_t *),
2039 KM_SLEEP);
2041 /* now allocate rx buffers */
2042 for (i = 0; i < MXFE_RXRING; i++) {
2043 mxfe_rxbuf_t *rxb = mxfe_allocrxbuf(mxfep);
2044 if (rxb == NULL)
2045 return (DDI_FAILURE);
2046 mxfep->mxfe_rxbufs[i] = rxb;
2049 return (DDI_SUCCESS);
2053 * Allocate transmit resources.
2056 mxfe_alloctxring(mxfe_t *mxfep)
2058 int rval;
2059 int i;
2060 size_t size;
2061 size_t len;
2062 ddi_dma_cookie_t dmac;
2063 unsigned ncookies;
2064 caddr_t kaddr;
2066 size = MXFE_TXRING * sizeof (mxfe_desc_t);
2068 rval = ddi_dma_alloc_handle(mxfep->mxfe_dip, &mxfe_dma_attr,
2069 DDI_DMA_SLEEP, NULL, &mxfep->mxfe_txdesc_dmah);
2070 if (rval != DDI_SUCCESS) {
2071 mxfe_error(mxfep->mxfe_dip,
2072 "unable to allocate DMA handle for tx descriptors");
2073 return (DDI_FAILURE);
2076 rval = ddi_dma_mem_alloc(mxfep->mxfe_txdesc_dmah, size, &mxfe_devattr,
2077 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
2078 &mxfep->mxfe_txdesc_acch);
2079 if (rval != DDI_SUCCESS) {
2080 mxfe_error(mxfep->mxfe_dip,
2081 "unable to allocate DMA memory for tx descriptors");
2082 return (DDI_FAILURE);
2085 rval = ddi_dma_addr_bind_handle(mxfep->mxfe_txdesc_dmah, NULL, kaddr,
2086 size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
2087 &dmac, &ncookies);
2088 if (rval != DDI_DMA_MAPPED) {
2089 mxfe_error(mxfep->mxfe_dip,
2090 "unable to bind DMA for tx descriptors");
2091 return (DDI_FAILURE);
2094 /* because of mxfe_dma_attr */
2095 ASSERT(ncookies == 1);
2097 /* we take the 32-bit physical address out of the cookie */
2098 mxfep->mxfe_txdesc_paddr = dmac.dmac_address;
2099 mxfep->mxfe_txdescp = (void *)kaddr;
2101 /* allocate buffer pointers (not the buffers themselves, yet) */
2102 mxfep->mxfe_txbufs = kmem_zalloc(MXFE_TXRING * sizeof (mxfe_txbuf_t *),
2103 KM_SLEEP);
2105 /* now allocate tx buffers */
2106 for (i = 0; i < MXFE_TXRING; i++) {
2107 mxfe_txbuf_t *txb = mxfe_alloctxbuf(mxfep);
2108 if (txb == NULL)
2109 return (DDI_FAILURE);
2110 /* stick it in the stack */
2111 mxfep->mxfe_txbufs[i] = txb;
2114 return (DDI_SUCCESS);
2117 void
2118 mxfe_freerxring(mxfe_t *mxfep)
2120 int i;
2122 for (i = 0; i < MXFE_RXRING; i++) {
2123 mxfe_destroyrxbuf(mxfep->mxfe_rxbufs[i]);
2126 if (mxfep->mxfe_rxbufs) {
2127 kmem_free(mxfep->mxfe_rxbufs,
2128 MXFE_RXRING * sizeof (mxfe_rxbuf_t *));
2131 if (mxfep->mxfe_rxdesc_paddr)
2132 (void) ddi_dma_unbind_handle(mxfep->mxfe_rxdesc_dmah);
2133 if (mxfep->mxfe_rxdesc_acch)
2134 ddi_dma_mem_free(&mxfep->mxfe_rxdesc_acch);
2135 if (mxfep->mxfe_rxdesc_dmah)
2136 ddi_dma_free_handle(&mxfep->mxfe_rxdesc_dmah);
2139 void
2140 mxfe_freetxring(mxfe_t *mxfep)
2142 int i;
2144 for (i = 0; i < MXFE_TXRING; i++) {
2145 mxfe_destroytxbuf(mxfep->mxfe_txbufs[i]);
2148 if (mxfep->mxfe_txbufs) {
2149 kmem_free(mxfep->mxfe_txbufs,
2150 MXFE_TXRING * sizeof (mxfe_txbuf_t *));
2152 if (mxfep->mxfe_txdesc_paddr)
2153 (void) ddi_dma_unbind_handle(mxfep->mxfe_txdesc_dmah);
2154 if (mxfep->mxfe_txdesc_acch)
2155 ddi_dma_mem_free(&mxfep->mxfe_txdesc_acch);
2156 if (mxfep->mxfe_txdesc_dmah)
2157 ddi_dma_free_handle(&mxfep->mxfe_txdesc_dmah);
2161 * Interrupt service routine.
2163 unsigned
2164 mxfe_intr(caddr_t arg)
2166 mxfe_t *mxfep = (void *)arg;
2167 uint32_t status;
2168 mblk_t *mp = NULL;
2169 boolean_t error = B_FALSE;
2171 mutex_enter(&mxfep->mxfe_intrlock);
2173 if (mxfep->mxfe_flags & MXFE_SUSPENDED) {
2174 /* we cannot receive interrupts! */
2175 mutex_exit(&mxfep->mxfe_intrlock);
2176 return (DDI_INTR_UNCLAIMED);
2179 /* check interrupt status bits, did we interrupt? */
2180 status = GETCSR(mxfep, CSR_SR) & INT_ALL;
2182 if (status == 0) {
2183 KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
2184 mutex_exit(&mxfep->mxfe_intrlock);
2185 return (DDI_INTR_UNCLAIMED);
2187 /* ack the interrupt */
2188 PUTCSR(mxfep, CSR_SR, status);
2189 KIOIP->intrs[KSTAT_INTR_HARD]++;
2191 if (!(mxfep->mxfe_flags & MXFE_RUNNING)) {
2192 /* not running, don't touch anything */
2193 mutex_exit(&mxfep->mxfe_intrlock);
2194 return (DDI_INTR_CLAIMED);
2197 if (status & INT_RXOK) {
2198 /* receive packets */
2199 if (mxfe_receive(mxfep, &mp)) {
2200 error = B_TRUE;
2204 if (status & INT_TXOK) {
2205 /* transmit completed */
2206 mutex_enter(&mxfep->mxfe_xmtlock);
2207 mxfe_reclaim(mxfep);
2208 mutex_exit(&mxfep->mxfe_xmtlock);
2211 if (((status & (INT_TIMER|INT_ANEG)) != 0) ||
2212 ((mxfep->mxfe_linkup == LINK_STATE_UP) &&
2213 ((status & (INT_10LINK|INT_100LINK)) != 0))) {
2214 /* rescan the link */
2215 mutex_enter(&mxfep->mxfe_xmtlock);
2216 mxfe_checklink(mxfep);
2217 mutex_exit(&mxfep->mxfe_xmtlock);
2220 if (status & (INT_RXSTOPPED|INT_TXSTOPPED|INT_RXNOBUF|
2221 INT_RXJABBER|INT_TXJABBER|INT_TXUNDERFLOW)) {
2223 if (status & (INT_RXJABBER | INT_TXJABBER)) {
2224 mxfep->mxfe_jabber++;
2226 DBG(DWARN, "error interrupt: status %x", status);
2227 error = B_TRUE;
2230 if (status & INT_BUSERR) {
2231 switch (status & SR_BERR_TYPE) {
2232 case SR_BERR_PARITY:
2233 mxfe_error(mxfep->mxfe_dip, "PCI parity error");
2234 break;
2235 case SR_BERR_TARGET_ABORT:
2236 mxfe_error(mxfep->mxfe_dip, "PCI target abort");
2237 break;
2238 case SR_BERR_MASTER_ABORT:
2239 mxfe_error(mxfep->mxfe_dip, "PCI master abort");
2240 break;
2241 default:
2242 mxfe_error(mxfep->mxfe_dip, "Unknown PCI error");
2243 break;
2246 error = B_TRUE;
2249 if (error) {
2250 /* reset the chip in an attempt to fix things */
2251 mutex_enter(&mxfep->mxfe_xmtlock);
2252 mxfe_resetall(mxfep);
2253 mutex_exit(&mxfep->mxfe_xmtlock);
2256 mutex_exit(&mxfep->mxfe_intrlock);
2259 * Send up packets. We do this outside of the intrlock.
2261 if (mp) {
2262 mac_rx(mxfep->mxfe_mh, NULL, mp);
2265 return (DDI_INTR_CLAIMED);
2268 void
2269 mxfe_enableinterrupts(mxfe_t *mxfep)
2271 unsigned mask = INT_WANTED;
2273 if (mxfep->mxfe_wantw)
2274 mask |= INT_TXOK;
2276 if (MXFE_MODEL(mxfep) != MXFE_98713A)
2277 mask |= INT_LINKSTATUS;
2279 DBG(DINTR, "setting int mask to 0x%x", mask);
2280 PUTCSR(mxfep, CSR_IER, mask);
2283 void
2284 mxfe_disableinterrupts(mxfe_t *mxfep)
2286 /* disable further interrupts */
2287 PUTCSR(mxfep, CSR_IER, 0);
2289 /* clear any pending interrupts */
2290 PUTCSR(mxfep, CSR_SR, INT_ALL);
2293 void
2294 mxfe_send_setup(mxfe_t *mxfep)
2296 mxfe_txbuf_t *txb;
2297 mxfe_desc_t *tmdp;
2299 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
2301 /* setup frame -- must be at head of list -- guaranteed by caller! */
2302 ASSERT(mxfep->mxfe_txsend == 0);
2304 txb = mxfep->mxfe_txbufs[0];
2305 tmdp = &mxfep->mxfe_txdescp[0];
2307 bzero(txb->txb_buf, MXFE_SETUP_LEN);
2309 /* program the unicast address */
2310 txb->txb_buf[156] = mxfep->mxfe_curraddr[0];
2311 txb->txb_buf[157] = mxfep->mxfe_curraddr[1];
2312 txb->txb_buf[160] = mxfep->mxfe_curraddr[2];
2313 txb->txb_buf[161] = mxfep->mxfe_curraddr[3];
2314 txb->txb_buf[164] = mxfep->mxfe_curraddr[4];
2315 txb->txb_buf[165] = mxfep->mxfe_curraddr[5];
2317 /* make sure that the hardware can see it */
2318 SYNCTXBUF(txb, MXFE_SETUP_LEN, DDI_DMA_SYNC_FORDEV);
2320 PUTTXDESC(mxfep, tmdp->desc_control,
2321 TXCTL_FIRST | TXCTL_LAST | TXCTL_INTCMPLTE | TXCTL_HASHPERF |
2322 TXCTL_SETUP | MXFE_SETUP_LEN);
2324 PUTTXDESC(mxfep, tmdp->desc_buffer1, txb->txb_paddr);
2325 PUTTXDESC(mxfep, tmdp->desc_buffer2, 0);
2326 PUTTXDESC(mxfep, tmdp->desc_status, TXSTAT_OWN);
2328 /* sync the descriptor out to the device */
2329 SYNCTXDESC(mxfep, 0, DDI_DMA_SYNC_FORDEV);
2332 * wake up the chip ... inside the lock to protect against DR suspend,
2333 * etc.
2335 PUTCSR(mxfep, CSR_TDR, 0);
2336 mxfep->mxfe_txsend++;
2337 mxfep->mxfe_txavail--;
2340 * Program promiscuous mode.
2342 if (mxfep->mxfe_promisc) {
2343 SETBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
2344 } else {
2345 CLRBIT(mxfep, CSR_NAR, NAR_RX_PROMISC);
2349 boolean_t
2350 mxfe_send(mxfe_t *mxfep, mblk_t *mp)
2352 size_t len;
2353 mxfe_txbuf_t *txb;
2354 mxfe_desc_t *tmd;
2355 uint32_t control;
2356 int txsend;
2358 ASSERT(mutex_owned(&mxfep->mxfe_xmtlock));
2359 ASSERT(mp != NULL);
2361 len = msgsize(mp);
2362 if (len > ETHERVLANMTU) {
2363 DBG(DXMIT, "frame too long: %d", len);
2364 mxfep->mxfe_macxmt_errors++;
2365 freemsg(mp);
2366 return (B_TRUE);
2369 if (mxfep->mxfe_txavail < MXFE_TXRECLAIM)
2370 mxfe_reclaim(mxfep);
2372 if (mxfep->mxfe_txavail == 0) {
2373 /* no more tmds */
2374 mxfep->mxfe_wantw = B_TRUE;
2375 /* enable TX interrupt */
2376 mxfe_enableinterrupts(mxfep);
2377 return (B_FALSE);
2380 txsend = mxfep->mxfe_txsend;
2383 * For simplicity, we just do a copy into a preallocated
2384 * DMA buffer.
2387 txb = mxfep->mxfe_txbufs[txsend];
2388 mcopymsg(mp, txb->txb_buf); /* frees mp! */
2391 * Statistics.
2393 mxfep->mxfe_opackets++;
2394 mxfep->mxfe_obytes += len;
2395 if (txb->txb_buf[0] & 0x1) {
2396 if (bcmp(txb->txb_buf, mxfe_broadcast, ETHERADDRL) != 0)
2397 mxfep->mxfe_multixmt++;
2398 else
2399 mxfep->mxfe_brdcstxmt++;
2402 /* note len is already known to be a small unsigned */
2403 control = len | TXCTL_FIRST | TXCTL_LAST | TXCTL_INTCMPLTE;
2405 if (txsend == (MXFE_TXRING - 1))
2406 control |= TXCTL_ENDRING;
2408 tmd = &mxfep->mxfe_txdescp[txsend];
2410 SYNCTXBUF(txb, len, DDI_DMA_SYNC_FORDEV);
2411 PUTTXDESC(mxfep, tmd->desc_control, control);
2412 PUTTXDESC(mxfep, tmd->desc_buffer1, txb->txb_paddr);
2413 PUTTXDESC(mxfep, tmd->desc_buffer2, 0);
2414 PUTTXDESC(mxfep, tmd->desc_status, TXSTAT_OWN);
2415 /* sync the descriptor out to the device */
2416 SYNCTXDESC(mxfep, txsend, DDI_DMA_SYNC_FORDEV);
2419 * Note the new values of txavail and txsend.
2421 mxfep->mxfe_txavail--;
2422 mxfep->mxfe_txsend = (txsend + 1) % MXFE_TXRING;
2425 * It should never, ever take more than 5 seconds to drain
2426 * the ring. If it happens, then we are stuck!
2428 mxfep->mxfe_txstall_time = gethrtime() + (5 * 1000000000ULL);
2431 * wake up the chip ... inside the lock to protect against DR suspend,
2432 * etc.
2434 PUTCSR(mxfep, CSR_TDR, 0);
2436 return (B_TRUE);
2440 * Reclaim buffers that have completed transmission.
2442 void
2443 mxfe_reclaim(mxfe_t *mxfep)
2445 mxfe_desc_t *tmdp;
2447 while (mxfep->mxfe_txavail != MXFE_TXRING) {
2448 uint32_t status;
2449 uint32_t control;
2450 int index = mxfep->mxfe_txreclaim;
2452 tmdp = &mxfep->mxfe_txdescp[index];
2454 /* sync it before we read it */
2455 SYNCTXDESC(mxfep, index, DDI_DMA_SYNC_FORKERNEL);
2457 control = GETTXDESC(mxfep, tmdp->desc_control);
2458 status = GETTXDESC(mxfep, tmdp->desc_status);
2460 if (status & TXSTAT_OWN) {
2461 /* chip is still working on it, we're done */
2462 break;
2465 mxfep->mxfe_txavail++;
2466 mxfep->mxfe_txreclaim = (index + 1) % MXFE_TXRING;
2468 /* in the most common successful case, all bits are clear */
2469 if (status == 0)
2470 continue;
2472 if (((control & TXCTL_SETUP) != 0) ||
2473 ((control & TXCTL_LAST) == 0)) {
2474 /* no interesting statistics here */
2475 continue;
2478 if (status & TXSTAT_TXERR) {
2479 mxfep->mxfe_errxmt++;
2481 if (status & TXSTAT_JABBER) {
2482 /* transmit jabber timeout */
2483 mxfep->mxfe_macxmt_errors++;
2485 if (status & (TXSTAT_CARRLOST | TXSTAT_NOCARR)) {
2486 mxfep->mxfe_carrier_errors++;
2488 if (status & TXSTAT_UFLOW) {
2489 mxfep->mxfe_underflow++;
2491 if (status & TXSTAT_LATECOL) {
2492 mxfep->mxfe_tx_late_collisions++;
2494 if (status & TXSTAT_EXCOLL) {
2495 mxfep->mxfe_ex_collisions++;
2496 mxfep->mxfe_collisions += 16;
2500 if (status & TXSTAT_DEFER) {
2501 mxfep->mxfe_defer_xmts++;
2504 /* collision counting */
2505 if (TXCOLLCNT(status) == 1) {
2506 mxfep->mxfe_collisions++;
2507 mxfep->mxfe_first_collisions++;
2508 } else if (TXCOLLCNT(status)) {
2509 mxfep->mxfe_collisions += TXCOLLCNT(status);
2510 mxfep->mxfe_multi_collisions += TXCOLLCNT(status);
2514 if (mxfep->mxfe_txavail >= MXFE_TXRESCHED) {
2515 if (mxfep->mxfe_wantw) {
2517 * we were able to reclaim some packets, so
2518 * disable tx interrupts
2520 mxfep->mxfe_wantw = B_FALSE;
2521 mxfe_enableinterrupts(mxfep);
2522 mac_tx_update(mxfep->mxfe_mh);
2527 boolean_t
2528 mxfe_receive(mxfe_t *mxfep, mblk_t **rxchain)
2530 unsigned len;
2531 mxfe_rxbuf_t *rxb;
2532 mxfe_desc_t *rmd;
2533 uint32_t status;
2534 mblk_t *mpchain, **mpp, *mp;
2535 int head, cnt;
2536 boolean_t error = B_FALSE;
2538 mpchain = NULL;
2539 mpp = &mpchain;
2540 head = mxfep->mxfe_rxhead;
2542 /* limit the number of packets we process to a ring size */
2543 for (cnt = 0; cnt < MXFE_RXRING; cnt++) {
2545 DBG(DRECV, "receive at index %d", head);
2547 rmd = &mxfep->mxfe_rxdescp[head];
2548 rxb = mxfep->mxfe_rxbufs[head];
2550 SYNCRXDESC(mxfep, head, DDI_DMA_SYNC_FORKERNEL);
2551 status = GETRXDESC(mxfep, rmd->desc_status);
2552 if (status & RXSTAT_OWN) {
2553 /* chip is still chewing on it */
2554 break;
2557 /* discard the ethernet frame checksum */
2558 len = RXLENGTH(status) - ETHERFCSL;
2560 DBG(DRECV, "recv length %d, status %x", len, status);
2562 if ((status & (RXSTAT_ERRS | RXSTAT_FIRST | RXSTAT_LAST)) !=
2563 (RXSTAT_FIRST | RXSTAT_LAST)) {
2565 mxfep->mxfe_errrcv++;
2568 * Abnormal status bits detected, analyze further.
2570 if ((status & (RXSTAT_LAST|RXSTAT_FIRST)) !=
2571 (RXSTAT_LAST|RXSTAT_FIRST)) {
2572 /* someone trying to send jumbo frames? */
2573 DBG(DRECV, "rx packet overspill");
2574 if (status & RXSTAT_FIRST) {
2575 mxfep->mxfe_toolong_errors++;
2577 } else if (status & RXSTAT_DESCERR) {
2578 /* this should never occur! */
2579 mxfep->mxfe_macrcv_errors++;
2580 error = B_TRUE;
2582 } else if (status & RXSTAT_RUNT) {
2583 mxfep->mxfe_runt++;
2585 } else if (status & RXSTAT_COLLSEEN) {
2586 /* this should really be rx_late_collisions */
2587 mxfep->mxfe_macrcv_errors++;
2589 } else if (status & RXSTAT_DRIBBLE) {
2590 mxfep->mxfe_align_errors++;
2592 } else if (status & RXSTAT_CRCERR) {
2593 mxfep->mxfe_fcs_errors++;
2595 } else if (status & RXSTAT_OFLOW) {
2596 /* this is a MAC FIFO error, need to reset */
2597 mxfep->mxfe_overflow++;
2598 error = B_TRUE;
2602 else if (len > ETHERVLANMTU) {
2603 mxfep->mxfe_errrcv++;
2604 mxfep->mxfe_toolong_errors++;
2608 * At this point, the chip thinks the packet is OK.
2610 else {
2611 mp = allocb(len + MXFE_HEADROOM, 0);
2612 if (mp == NULL) {
2613 mxfep->mxfe_errrcv++;
2614 mxfep->mxfe_norcvbuf++;
2615 goto skip;
2618 /* sync the buffer before we look at it */
2619 SYNCRXBUF(rxb, len, DDI_DMA_SYNC_FORKERNEL);
2620 mp->b_rptr += MXFE_HEADROOM;
2621 mp->b_wptr = mp->b_rptr + len;
2622 bcopy((char *)rxb->rxb_buf, mp->b_rptr, len);
2624 mxfep->mxfe_ipackets++;
2625 mxfep->mxfe_rbytes += len;
2626 if (status & RXSTAT_GROUP) {
2627 if (bcmp(mp->b_rptr, mxfe_broadcast,
2628 ETHERADDRL) == 0)
2629 mxfep->mxfe_brdcstrcv++;
2630 else
2631 mxfep->mxfe_multircv++;
2633 *mpp = mp;
2634 mpp = &mp->b_next;
2637 skip:
2638 /* return ring entry to the hardware */
2639 PUTRXDESC(mxfep, rmd->desc_status, RXSTAT_OWN);
2640 SYNCRXDESC(mxfep, head, DDI_DMA_SYNC_FORDEV);
2642 /* advance to next RMD */
2643 head = (head + 1) % MXFE_RXRING;
2646 mxfep->mxfe_rxhead = head;
2648 *rxchain = mpchain;
2649 return (error);
2653 mxfe_m_stat(void *arg, uint_t stat, uint64_t *val)
2655 mxfe_t *mxfep = arg;
2657 mutex_enter(&mxfep->mxfe_xmtlock);
2658 if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) == MXFE_RUNNING)
2659 mxfe_reclaim(mxfep);
2660 mutex_exit(&mxfep->mxfe_xmtlock);
2662 switch (stat) {
2663 case MAC_STAT_IFSPEED:
2664 *val = mxfep->mxfe_ifspeed;
2665 break;
2667 case MAC_STAT_MULTIRCV:
2668 *val = mxfep->mxfe_multircv;
2669 break;
2671 case MAC_STAT_BRDCSTRCV:
2672 *val = mxfep->mxfe_brdcstrcv;
2673 break;
2675 case MAC_STAT_MULTIXMT:
2676 *val = mxfep->mxfe_multixmt;
2677 break;
2679 case MAC_STAT_BRDCSTXMT:
2680 *val = mxfep->mxfe_brdcstxmt;
2681 break;
2683 case MAC_STAT_IPACKETS:
2684 *val = mxfep->mxfe_ipackets;
2685 break;
2687 case MAC_STAT_RBYTES:
2688 *val = mxfep->mxfe_rbytes;
2689 break;
2691 case MAC_STAT_OPACKETS:
2692 *val = mxfep->mxfe_opackets;
2693 break;
2695 case MAC_STAT_OBYTES:
2696 *val = mxfep->mxfe_obytes;
2697 break;
2699 case MAC_STAT_NORCVBUF:
2700 *val = mxfep->mxfe_norcvbuf;
2701 break;
2703 case MAC_STAT_NOXMTBUF:
2704 *val = mxfep->mxfe_noxmtbuf;
2705 break;
2707 case MAC_STAT_COLLISIONS:
2708 *val = mxfep->mxfe_collisions;
2709 break;
2711 case MAC_STAT_IERRORS:
2712 *val = mxfep->mxfe_errrcv;
2713 break;
2715 case MAC_STAT_OERRORS:
2716 *val = mxfep->mxfe_errxmt;
2717 break;
2719 case ETHER_STAT_LINK_DUPLEX:
2720 *val = mxfep->mxfe_duplex;
2721 break;
2723 case ETHER_STAT_ALIGN_ERRORS:
2724 *val = mxfep->mxfe_align_errors;
2725 break;
2727 case ETHER_STAT_FCS_ERRORS:
2728 *val = mxfep->mxfe_fcs_errors;
2729 break;
2731 case ETHER_STAT_SQE_ERRORS:
2732 *val = mxfep->mxfe_sqe_errors;
2733 break;
2735 case ETHER_STAT_DEFER_XMTS:
2736 *val = mxfep->mxfe_defer_xmts;
2737 break;
2739 case ETHER_STAT_FIRST_COLLISIONS:
2740 *val = mxfep->mxfe_first_collisions;
2741 break;
2743 case ETHER_STAT_MULTI_COLLISIONS:
2744 *val = mxfep->mxfe_multi_collisions;
2745 break;
2747 case ETHER_STAT_TX_LATE_COLLISIONS:
2748 *val = mxfep->mxfe_tx_late_collisions;
2749 break;
2751 case ETHER_STAT_EX_COLLISIONS:
2752 *val = mxfep->mxfe_ex_collisions;
2753 break;
2755 case ETHER_STAT_MACXMT_ERRORS:
2756 *val = mxfep->mxfe_macxmt_errors;
2757 break;
2759 case ETHER_STAT_CARRIER_ERRORS:
2760 *val = mxfep->mxfe_carrier_errors;
2761 break;
2763 case ETHER_STAT_TOOLONG_ERRORS:
2764 *val = mxfep->mxfe_toolong_errors;
2765 break;
2767 case ETHER_STAT_MACRCV_ERRORS:
2768 *val = mxfep->mxfe_macrcv_errors;
2769 break;
2771 case MAC_STAT_OVERFLOWS:
2772 *val = mxfep->mxfe_overflow;
2773 break;
2775 case MAC_STAT_UNDERFLOWS:
2776 *val = mxfep->mxfe_underflow;
2777 break;
2779 case ETHER_STAT_TOOSHORT_ERRORS:
2780 *val = mxfep->mxfe_runt;
2781 break;
2783 case ETHER_STAT_JABBER_ERRORS:
2784 *val = mxfep->mxfe_jabber;
2785 break;
2787 case ETHER_STAT_ADV_CAP_100T4:
2788 *val = mxfep->mxfe_adv_100T4;
2789 break;
2791 case ETHER_STAT_LP_CAP_100T4:
2792 *val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_T4) ? 1 : 0;
2793 break;
2795 case ETHER_STAT_CAP_100T4:
2796 *val = mxfep->mxfe_cap_100T4;
2797 break;
2799 case ETHER_STAT_CAP_100FDX:
2800 *val = mxfep->mxfe_cap_100fdx;
2801 break;
2803 case ETHER_STAT_CAP_100HDX:
2804 *val = mxfep->mxfe_cap_100hdx;
2805 break;
2807 case ETHER_STAT_CAP_10FDX:
2808 *val = mxfep->mxfe_cap_10fdx;
2809 break;
2811 case ETHER_STAT_CAP_10HDX:
2812 *val = mxfep->mxfe_cap_10hdx;
2813 break;
2815 case ETHER_STAT_CAP_AUTONEG:
2816 *val = mxfep->mxfe_cap_aneg;
2817 break;
2819 case ETHER_STAT_LINK_AUTONEG:
2820 *val = ((mxfep->mxfe_adv_aneg != 0) &&
2821 ((mxfep->mxfe_aner & MII_AN_EXP_LPCANAN) != 0));
2822 break;
2824 case ETHER_STAT_ADV_CAP_100FDX:
2825 *val = mxfep->mxfe_adv_100fdx;
2826 break;
2828 case ETHER_STAT_ADV_CAP_100HDX:
2829 *val = mxfep->mxfe_adv_100hdx;
2830 break;
2832 case ETHER_STAT_ADV_CAP_10FDX:
2833 *val = mxfep->mxfe_adv_10fdx;
2834 break;
2836 case ETHER_STAT_ADV_CAP_10HDX:
2837 *val = mxfep->mxfe_adv_10hdx;
2838 break;
2840 case ETHER_STAT_ADV_CAP_AUTONEG:
2841 *val = mxfep->mxfe_adv_aneg;
2842 break;
2844 case ETHER_STAT_LP_CAP_100FDX:
2845 *val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_TX_FD) ? 1 : 0;
2846 break;
2848 case ETHER_STAT_LP_CAP_100HDX:
2849 *val = (mxfep->mxfe_anlpar & MII_ABILITY_100BASE_TX) ? 1 : 0;
2850 break;
2852 case ETHER_STAT_LP_CAP_10FDX:
2853 *val = (mxfep->mxfe_anlpar & MII_ABILITY_10BASE_T_FD) ? 1 : 0;
2854 break;
2856 case ETHER_STAT_LP_CAP_10HDX:
2857 *val = (mxfep->mxfe_anlpar & MII_ABILITY_10BASE_T) ? 1 : 0;
2858 break;
2860 case ETHER_STAT_LP_CAP_AUTONEG:
2861 *val = (mxfep->mxfe_aner & MII_AN_EXP_LPCANAN) ? 1 : 0;
2862 break;
2864 case ETHER_STAT_XCVR_ADDR:
2865 *val = mxfep->mxfe_phyaddr;
2866 break;
2868 case ETHER_STAT_XCVR_ID:
2869 *val = mxfep->mxfe_phyid;
2870 break;
2872 case ETHER_STAT_XCVR_INUSE:
2873 *val = mxfep->mxfe_phyinuse;
2874 break;
2876 default:
2877 return (ENOTSUP);
2879 return (0);
2882 /*ARGSUSED*/
2884 mxfe_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
2885 void *val)
2887 mxfe_t *mxfep = arg;
2888 int err = 0;
2890 switch (num) {
2891 case MAC_PROP_DUPLEX:
2892 ASSERT(sz >= sizeof (link_duplex_t));
2893 bcopy(&mxfep->mxfe_duplex, val, sizeof (link_duplex_t));
2894 break;
2896 case MAC_PROP_SPEED:
2897 ASSERT(sz >= sizeof (uint64_t));
2898 bcopy(&mxfep->mxfe_ifspeed, val, sizeof (uint64_t));
2899 break;
2901 case MAC_PROP_AUTONEG:
2902 *(uint8_t *)val = mxfep->mxfe_adv_aneg;
2903 break;
2905 case MAC_PROP_ADV_100FDX_CAP:
2906 case MAC_PROP_EN_100FDX_CAP:
2907 *(uint8_t *)val = mxfep->mxfe_adv_100fdx;
2908 break;
2910 case MAC_PROP_ADV_100HDX_CAP:
2911 case MAC_PROP_EN_100HDX_CAP:
2912 *(uint8_t *)val = mxfep->mxfe_adv_100hdx;
2913 break;
2915 case MAC_PROP_ADV_10FDX_CAP:
2916 case MAC_PROP_EN_10FDX_CAP:
2917 *(uint8_t *)val = mxfep->mxfe_adv_10fdx;
2918 break;
2920 case MAC_PROP_ADV_10HDX_CAP:
2921 case MAC_PROP_EN_10HDX_CAP:
2922 *(uint8_t *)val = mxfep->mxfe_adv_10hdx;
2923 break;
2925 case MAC_PROP_ADV_100T4_CAP:
2926 case MAC_PROP_EN_100T4_CAP:
2927 *(uint8_t *)val = mxfep->mxfe_adv_100T4;
2928 break;
2930 default:
2931 err = ENOTSUP;
2934 return (err);
2937 /*ARGSUSED*/
2939 mxfe_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
2940 const void *val)
2942 mxfe_t *mxfep = arg;
2943 uint8_t *advp;
2944 uint8_t *capp;
2946 switch (num) {
2947 case MAC_PROP_EN_100FDX_CAP:
2948 advp = &mxfep->mxfe_adv_100fdx;
2949 capp = &mxfep->mxfe_cap_100fdx;
2950 break;
2952 case MAC_PROP_EN_100HDX_CAP:
2953 advp = &mxfep->mxfe_adv_100hdx;
2954 capp = &mxfep->mxfe_cap_100hdx;
2955 break;
2957 case MAC_PROP_EN_10FDX_CAP:
2958 advp = &mxfep->mxfe_adv_10fdx;
2959 capp = &mxfep->mxfe_cap_10fdx;
2960 break;
2962 case MAC_PROP_EN_10HDX_CAP:
2963 advp = &mxfep->mxfe_adv_10hdx;
2964 capp = &mxfep->mxfe_cap_10hdx;
2965 break;
2967 case MAC_PROP_EN_100T4_CAP:
2968 advp = &mxfep->mxfe_adv_100T4;
2969 capp = &mxfep->mxfe_cap_100T4;
2970 break;
2972 case MAC_PROP_AUTONEG:
2973 advp = &mxfep->mxfe_adv_aneg;
2974 capp = &mxfep->mxfe_cap_aneg;
2975 break;
2977 default:
2978 return (ENOTSUP);
2981 if (*capp == 0) /* ensure phy can support value */
2982 return (ENOTSUP);
2984 mutex_enter(&mxfep->mxfe_intrlock);
2985 mutex_enter(&mxfep->mxfe_xmtlock);
2987 if (*advp != *(const uint8_t *)val) {
2988 *advp = *(const uint8_t *)val;
2990 if ((mxfep->mxfe_flags & (MXFE_RUNNING|MXFE_SUSPENDED)) ==
2991 MXFE_RUNNING) {
2993 * This re-initializes the phy, but it also
2994 * restarts transmit and receive rings.
2995 * Needless to say, changing the link
2996 * parameters is destructive to traffic in
2997 * progress.
2999 mxfe_resetall(mxfep);
3002 mutex_exit(&mxfep->mxfe_xmtlock);
3003 mutex_exit(&mxfep->mxfe_intrlock);
3005 return (0);
3008 static void
3009 mxfe_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
3010 mac_prop_info_handle_t mph)
3012 mxfe_t *mxfep = arg;
3014 _NOTE(ARGUNUSED(name));
3016 switch (num) {
3017 case MAC_PROP_DUPLEX:
3018 case MAC_PROP_SPEED:
3019 case MAC_PROP_ADV_100FDX_CAP:
3020 case MAC_PROP_ADV_100HDX_CAP:
3021 case MAC_PROP_ADV_10FDX_CAP:
3022 case MAC_PROP_ADV_10HDX_CAP:
3023 case MAC_PROP_ADV_100T4_CAP:
3024 mac_prop_info_set_perm(mph, MAC_PROP_PERM_READ);
3025 break;
3027 case MAC_PROP_AUTONEG:
3028 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_aneg);
3029 break;
3031 case MAC_PROP_EN_100FDX_CAP:
3032 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_100fdx);
3033 break;
3035 case MAC_PROP_EN_100HDX_CAP:
3036 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_100hdx);
3037 break;
3039 case MAC_PROP_EN_10FDX_CAP:
3040 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_10fdx);
3041 break;
3043 case MAC_PROP_EN_10HDX_CAP:
3044 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_10hdx);
3045 break;
3047 case MAC_PROP_EN_100T4_CAP:
3048 mac_prop_info_set_default_uint8(mph, mxfep->mxfe_cap_100T4);
3049 break;
3054 * Debugging and error reporting.
3056 void
3057 mxfe_error(dev_info_t *dip, char *fmt, ...)
3059 va_list ap;
3060 char buf[256];
3062 va_start(ap, fmt);
3063 (void) vsnprintf(buf, sizeof (buf), fmt, ap);
3064 va_end(ap);
3066 if (dip) {
3067 cmn_err(CE_WARN, "%s%d: %s",
3068 ddi_driver_name(dip), ddi_get_instance(dip), buf);
3069 } else {
3070 cmn_err(CE_WARN, "mxfe: %s", buf);
3074 #ifdef DEBUG
3076 void
3077 mxfe_dprintf(mxfe_t *mxfep, const char *func, int level, char *fmt, ...)
3079 va_list ap;
3081 va_start(ap, fmt);
3082 if (mxfe_debug & level) {
3083 char tag[64];
3084 char buf[256];
3086 if (mxfep && mxfep->mxfe_dip) {
3087 (void) snprintf(tag, sizeof (tag),
3088 "%s%d", ddi_driver_name(mxfep->mxfe_dip),
3089 ddi_get_instance(mxfep->mxfe_dip));
3090 } else {
3091 (void) snprintf(tag, sizeof (tag), "mxfe");
3094 (void) snprintf(buf, sizeof (buf), "%s: %s: %s\n", tag,
3095 func, fmt);
3097 vcmn_err(CE_CONT, buf, ap);
3099 va_end(ap);
3102 #endif