69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Use is subject to license terms.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Copyright (c) 1998 The NetBSD Foundation, Inc.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * All rights reserved.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This code is derived from software contributed to The NetBSD Foundation
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * by Frank van der Linden.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Redistribution and use in source and binary forms, with or without
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * modification, are permitted provided that the following conditions
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * 1. Redistributions of source code must retain the above copyright
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * notice, this list of conditions and the following disclaimer.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * notice, this list of conditions and the following disclaimer in the
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * documentation and/or other materials provided with the distribution.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * POSSIBILITY OF SUCH DAMAGE.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic uint16_t elxl_read_eeprom(elxl_t *, int);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic uint16_t elxl_mii_read(void *, uint8_t, uint8_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic void elxl_mii_write(void *, uint8_t, uint8_t, uint16_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic void elxl_mii_notify(void *, link_state_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_stat(void *, uint_t, uint64_t *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_start(void *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic void elxl_m_stop(void *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_promisc(void *, boolean_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_multicst(void *, boolean_t, const uint8_t *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_unicst(void *, const uint8_t *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore const void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void elxl_m_propinfo(void *, const char *, mac_prop_id_t,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic boolean_t elxl_m_getcapab(void *, mac_capab_t cap, void *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic void elxl_error(elxl_t *, char *, ...);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic void elxl_linkcheck(void *);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic int elxl_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic ddi_device_acc_attr_t ex_dev_acc_attr = {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amorestatic ddi_device_acc_attr_t ex_buf_acc_attr = {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * In theory buffers can have more flexible DMA attributes, but since
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * we're just using a preallocated region with bcopy, there is little
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * reason to allow for rougher alignment. (Further, the 8-byte
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * alignment can allow for more efficient bcopy and similar operations
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * from the buffer.)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore 0, /* dma_attr_addr_lo */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore 0 /* dma_attr_flags */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Structure to map media-present bits in boards to ifmedia codes and
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * printable media names. Used for table-driven ifmedia initialization.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Media table for 3c90x chips. Note that chips with MII have no
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * `native' media. This is sorted in "reverse preference".
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore { MEDIAOPT_100TX, XCVR_SEL_AUTO }, /* only 90XB */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * NB: There are lots of other models that *could* be supported.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Specifically there are cardbus and miniPCI variants that could be
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * easily added here, but they require special hacks and I have no
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * access to the hardware required to verify them. Especially they
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * seem to require some extra work in another register window, and I
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * have no supporting documentation.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore unsigned epp_flags; /* initial softc flags */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer "_available_media",
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Stream information
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'AmoreDDI_DEFINE_STREAM_OPS(ex_devops, nulldev, nulldev,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Module linkage information.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((rv = mod_install(&ex_modlinkage)) != DDI_SUCCESS) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((rv = mod_remove(&ex_modlinkage)) == DDI_SUCCESS) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore return (mod_info(&ex_modlinkage, modinfop));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = 0; i < r->r_count; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore kmem_free(r->r_desc, sizeof (ex_desc_t) * r->r_count);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* transmit ring, not linked yet */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = 0; i < r->r_count; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* receive is linked into a list */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = 0; i < r->r_count; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_PD(r, pd->pd_link, ed->ed_next->ed_descaddr);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_PD(r, pd->pd_len, EX_BUFSZ | EX_FR_LAST);
5109e3feb6ddd3a42752ef75689e774397813d0cGarrett D'Amore (void) ddi_dma_sync(r->r_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreex_alloc_ring(elxl_t *sc, int count, ex_ring_t *r, uint_t dir)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore r->r_desc = kmem_zalloc(sizeof (ex_desc_t) * count, KM_SLEEP);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_alloc_handle(dip, &ex_dma_attr, DDI_DMA_DONTWAIT,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "unable to allocate descriptor dma handle");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_mem_alloc(r->r_dmah, count * sizeof (struct ex_pd),
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore &ex_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "unable to allocate descriptor memory");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_addr_bind_handle(r->r_dmah, NULL,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (caddr_t)r->r_pd, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "unable to map descriptor memory");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (i = 0; i < count; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore ed->ed_descaddr = r->r_paddr + (i * sizeof (ex_pd_t));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Link the high level descriptors into a ring. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_alloc_handle(dip, &ex_dma_attr,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "can't allocate buf dma handle");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_mem_alloc(ed->ed_dmah, EX_BUFSZ, &ex_buf_acc_attr,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, &ed->ed_buf,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "unable to allocate buf memory");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_dma_addr_bind_handle(ed->ed_dmah, NULL,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = ddi_intr_alloc(dip, &sc->ex_intrh, DDI_INTR_TYPE_FIXED,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Unable to allocate interrupt, %d, count %d",
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (ddi_intr_get_pri(sc->ex_intrh, &ipri) != DDI_SUCCESS) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Unable to get interrupt priority");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (ddi_intr_add_handler(sc->ex_intrh, elxl_intr, sc, NULL) !=
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Can't add interrupt handler");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore mutex_init(&sc->ex_intrlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore mutex_init(&sc->ex_txlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (pci_config_setup(dip, &sc->ex_pcih) != DDI_SUCCESS) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "unable to setup PCI config handle");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore venid = pci_config_get16(sc->ex_pcih, PCI_CONF_VENID);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore devid = pci_config_get16(sc->ex_pcih, PCI_CONF_DEVID);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Not a 3Com part! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Unsupported vendor id (0x%x)", venid);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Not a produce we know how to support */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Unsupported device id (0x%x)", devid);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Driver may or may not function.");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore pci_config_put16(sc->ex_pcih, PCI_CONF_COMM,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore pci_config_get16(sc->ex_pcih, PCI_CONF_COMM) |
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (ddi_regs_map_setup(dip, 1, &sc->ex_regsva, 0, 0, &ex_dev_acc_attr,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Unable to map device registers");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore sc->ex_capab = elxl_read_eeprom(sc, EE_CAPABILITIES);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Is this a 90XB? If bit 2 (supportsLargePackets) is set, or
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * bit (supportsNoTxLength) is clear, then its a 90X.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Otherwise its a 90XB.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((sc->ex_capab & (1 << 2)) || !(sc->ex_capab & (1 << 9))) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (!ex_alloc_ring(sc, EX_NRX, &sc->ex_rxring, DDI_DMA_READ)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (!ex_alloc_ring(sc, EX_NTX, &sc->ex_txring, DDI_DMA_WRITE)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * The probe may have indicated MII!
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (sc->ex_mediaopt & (MEDIAOPT_MII | MEDIAOPT_100TX)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore sc->ex_miih = mii_alloc(sc, sc->ex_dip, &ex_mii_ops);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Note: The 90XB models can in theory support pause,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * but we're not enabling now due to lack of units for
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * testing with. If this is changed, make sure to
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * update the code in elxl_mii_notify to set the flow
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * control field in the W3_MAC_CONTROL register.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore mii_set_pauseable(sc->ex_miih, B_FALSE, B_FALSE);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "MAC register allocation failed");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (mac_register(macp, &sc->ex_mach) == DDI_SUCCESS) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Note: we don't want to start link checking
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * until *after* we have added the MAC handle.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (MEDIAOPT_MASK & ~(MEDIAOPT_MII | MEDIAOPT_100TX))) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Check non-MII link state once per second. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore ddi_periodic_add(elxl_linkcheck, sc, 10000000, 0);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Find the media present on non-MII chips, and select the one to use.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * We modify the media_options field so that we have a
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * consistent view of the media available, without worrying
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * about the version of ASIC, etc.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * 100BASE-TX is handled differently on 90XB from 90X. Older
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * parts use the external MII to provide this support.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * 3Com advises that we should only ever use the
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * auto mode. Notably, it seems that there should
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * never be a 90XB board with the MEDIAOPT_10T bit set
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * without this bit. If it happens, the driver will
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * run in compatible 10BASE-T only mode.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * If this occurs, we really want to use it like
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * an MII device. Generally in this situation we
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * want to use the MII exclusively, and there ought
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * not be a 10bT transceiver.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Additionally, some of these devices map all
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * internal PHY register at *every* address, not
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * just the "allowed" address 24.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Early versions didn't have 10FL models, and used this
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * bit for something else (VCO).
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* 100BASE-T4 units all use the MII bus. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Save our media options. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) strlcat(str, *str ? "," : "", sizeof (str)); \
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, (MEDIAOPT_MII|MEDIAOPT_100TX), "mii");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, MEDIAOPT_10T, "tp-hdx,tp-fdx");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, MEDIAOPT_100FX, "fx-hdx,fx-fdx");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, MEDIAOPT_BNC, "bnc");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, MEDIAOPT_AUI, "aui");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore APPEND_MEDIA(sc->ex_medias, MEDIAOPT_10FL, "fl-hdx,fl-fdx");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Only found on 90XB. Don't use this, use AUTO instead! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Sanity check that there are any media! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore "No media present? Attempting to use default.");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This "default" may be non-sensical. At worst it should
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * cause a busted link.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (exm = ex_native_media; exm->exm_mpbit != 0; exm++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* preferred default is present, just use it */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* but keep trying for other more preferred options */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Setup transmitter parameters.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Disable reclaim threshold for 90xB, set free threshold to
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * 6 * 256 = 1536 for 90x.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * We've seen underflows at the root cause of NIC hangs on
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * older cards. Use a store-and-forward model to prevent that.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Bring device up.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Load Tx parameters. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT32(REG_DMACTRL, GET32(REG_DMACTRL) | DMACTRL_UPRXEAREN);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Configure for VLAN tag sizing. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W3_MAC_CONTROL, GET16(W3_MAC_CONTROL) |
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT32(REG_UPLISTPTR, sc->ex_rxring.r_paddr);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Set multicast receive filter. Also take care of promiscuous mode.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Note that *some* of this hardware is fully capable of either a 256
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * or 64 bit multicast hash. However, we can't determine what the
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * size of the hash table is easily, and so we are expected to be able
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * to resubmit the entire list of addresses each time. This puts an
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * onerous burden on the driver to maintain its list of multicast
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * addresses. Since multicast stuff is usually not that performance
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * sensitive, and since we don't usually have much of it, we are just
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * going to skip it. We allow the upper layers to filter it, as
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * needed, by setting the all-multicast bit if the hardware can do it.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This also reduces our test burden.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore uint16_t mask = FILTER_UNICAST | FILTER_ALLBCAST;
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Set the station address and clear the station mask. The latter
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * is needed for 90x cards, 0 is the default for 90xB cards.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = 0; i < ETHERADDRL; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT8(W2_STATION_ADDRESS + i, sc->ex_curraddr[i]);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Now turn on the selected media/transceiver.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore MEDIASTAT_JABGUARD_EN | MEDIASTAT_LINKBEAT_EN);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore sc->ex_mii_active = B_FALSE; /* Is this really true? */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This is due to paranoia. If a card claims
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * to default to MII, but doesn't have it set in
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * media options, then we don't want to leave
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * the MII active or we'll have problems derferencing
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * the "mii handle".
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Impossible media setting!");
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * If we're not using MII, force the full-duplex setting. MII
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * based modes handle the full-duplex setting via the MII
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * notify callback.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Get currently-selected media from card.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * (if_media callback, may be called before interface is brought up).
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* these media we can detect link on */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* these media we can detect link on */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * For these we don't really know the answer,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * but if we lie then at least it won't cause
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * ifconfig to turn off the RUNNING flag.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This is necessary because we might
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * transition from LINK_STATE_DOWN when
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * switching media.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore sc->ex_duplex = GET16(W3_MAC_CONTROL) & MAC_CONTROL_FDX ?
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_m_multicst(void *arg, boolean_t add, const uint8_t *addr)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_m_unicst(void *arg, const uint8_t *addr)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int limit = (EX_NTX * 2); limit; limit--) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* first reclaim any free descriptors */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* still processing this one, we're done */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* done processing the entire list! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((r->r_avail < r->r_count) && (GET32(REG_DNLISTPTR) != 0)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * If there is already a tx list, select the next desc on the list.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Otherwise, just pick the first descriptor.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore cflags |= (EX_DPD_TCPCKSUM | EX_DPD_UDPCKSUM);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Mark this descriptor is in use. We're committed now. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore mcopymsg(mp, txd->ed_buf); /* frees the mblk! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Accounting stuff. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (bcmp(txd->ed_buf, ex_broadcast, ETHERADDRL) != 0) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Zero pad the frame if its too short. This
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * also avoids a checksum offload bug.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * If this our first packet so far, record the head
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * of the list.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) ddi_dma_sync(txd->ed_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Write the link into the previous descriptor. Note that
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * if this is the first packet (so no previous queued), this
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * will be benign because the previous descriptor won't be
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * on any tx list. (Furthermore, we'll clear its link field
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * when we do later use it.)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_PD(r, txd->ed_prev->ed_pd->pd_link, txd->ed_descaddr);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Are we submitting any packets?
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Interrupt on the last packet. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_PD(r, pd->pd_fsh, len | cflags | EX_DPD_DNIND);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* No packets pending, so its a new list head! */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* We've added frames, so don't interrupt mid-list. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Record the last descriptor. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* flush the entire ring - we're stopped so its safe */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) ddi_dma_sync(r->r_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Restart transmitter. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT32(REG_DNLISTPTR, sc->ex_txring.r_head->ed_descaddr);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_recv(elxl_t *sc, ex_desc_t *rxd, uint32_t stat)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (stat & (EX_UPD_ERR_VLAN | EX_UPD_OVERFLOW)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Allow four bytes for the VLAN header */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((mp = allocb(len + 14, BPRI_HI)) == NULL) {
5109e3feb6ddd3a42752ef75689e774397813d0cGarrett D'Amore (void) ddi_dma_sync(rxd->ed_dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (bcmp(rxd->ed_buf, ex_broadcast, ETHERADDRL) != 0) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Set the incoming checksum information for the packet.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (stat & (EX_UPD_TCPCHECKED | EX_UPD_UDPCHECKED)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore pflags |= (HCK_FULLCKSUM | HCK_FULLCKSUM_OK);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, 0, pflags, 0);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_m_getcapab(void *arg, mac_capab_t cap, void *data)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore *flags = HCKSUM_IPHDRCKSUM | HCKSUM_INET_FULL_V4;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerelxl_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer rv = mii_m_getprop(sc->ex_miih, name, num, sz, val);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore bcopy(&sc->ex_link, val, sizeof (link_state_t));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This available media property is a hack, and should
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * be removed when we can provide proper support for
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * querying it as proposed in PSARC 2009/235. (At the
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * moment the implementation lacks support for using
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * MAC_PROP_POSSIBLE with private properties.)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if (strcmp(name, "_available_media") == 0) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) snprintf(val, sz, "%s", sc->ex_medias);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore rv = mii_m_setprop(sc->ex_miih, name, num, sz, val);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* select media option */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* select media option */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerelxl_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_m_stat(void *arg, uint_t stat, uint64_t *val)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (mii_m_getstat(sc->ex_miih, stat, val) == 0)) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore *val = sc->ex_jabber + sc->ex_latecol + sc->ex_uflo;
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore *val = sc->ex_align + sc->ex_fcs + sc->ex_runt +
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore sc->ex_toolong + sc->ex_oflo + sc->ex_allocbfail;
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Acknowledge interrupts.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_CMD(CMD_INT_ACK | (stat & INT_WATCHED) | INT_LATCH);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* XXX: Potentially a good spot for FMA */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_error(sc, "Adapter failure (%x)", stat);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Advance head to next packet. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((mp = elxl_recv(sc, rxd, pktstat)) != NULL) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* clear the upComplete status, reset other fields */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT_PD(r, pd->pd_len, EX_BUFSZ | EX_FR_LAST);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * If the engine stalled processing (due to
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * insufficient UPDs usually), restart it.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * This seems that it can happen in an RX overrun
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * We count the packets and bytes elsewhere, but we need to
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * read the registers to clear them.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) GET8(W6_RX_OVERRUNS); /* counted by elxl_recv */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Note: we ought to report this somewhere... */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Some ASICs need a longer time (20 ms) to come properly out
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * of reset. Do not reduce this value.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Note that this occurs only during attach and failure recovery,
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * so it should be mostly harmless.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_reset_ring(&sc->ex_rxring, DDI_DMA_READ);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore elxl_reset_ring(&sc->ex_txring, DDI_DMA_WRITE);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Disable all interrupts. (0 means "none".) */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* This should always succeed. */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* Detach all PHYs */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) ddi_intr_remove_handler(sc->ex_intrh);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * Read EEPROM data. If we can't unbusy the EEPROM, then zero will be
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * returned. This will probably result in a bogus node address.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W0_EE_CMD, EE_CMD_READ | (offset & 0x3f));
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore int i = 2000;
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore while (i--) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreex_mii_send_bits(struct ex_softc *sc, uint16_t bits, int cnt)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = (1 << (cnt - 1)); i; i >>= 1) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore * We set the data bit output, and strobe the clock 32 times.
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (int i = 0; i < 32; i++) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR | PHYSMGMT_CLK);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_mii_read(void *arg, uint8_t phy, uint8_t reg)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((sc->ex_conf & CONF_INTPHY) && phy != INTPHY_ID)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore return (0xffff);
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore ex_mii_send_bits(sc, 2, 2); /* read command */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, 0); /* switch to input */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, PHYSMGMT_CLK); /* turnaround time */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore PUT16(W4_PHYSMGMT, PHYSMGMT_CLK); /* idle time */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore for (data = 0, val = 0x8000; val; val >>= 1) {
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* strobe the clock */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* return to output mode */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore if ((sc->ex_conf & CONF_INTPHY) && phy != INTPHY_ID)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore ex_mii_send_bits(sc, 2, 2); /* ack/turnaround */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* return to output mode */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_mii_notify(void *arg, link_state_t link)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore /* If we're using some other legacy media, bail out now */
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amoreelxl_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
69b3e10436272b0970d58743de375d0dd61046ceGarrett D'Amore (void) vsnprintf(buf, sizeof (buf), fmt, ap);