2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * CDDL HEADER START
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The contents of this file are subject to the terms of the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Common Development and Distribution License (the "License").
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * You may not use this file except in compliance with the License.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * or http://www.opensolaris.org/os/licensing.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * See the License for the specific language governing permissions
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * and limitations under the License.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * When distributing Covered Code, include this CDDL HEADER in each
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If applicable, add the following below this CDDL HEADER, with the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * fields enclosed by brackets "[]" replaced with your own identifying
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * information: Portions Copyright [yyyy] [name of copyright owner]
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * CDDL HEADER END
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Use is subject to license terms.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/types.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/stream.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/strsun.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/stat.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/pci.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/modctl.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/kstat.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/ethernet.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/devops.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/debug.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/conf.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/mac.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/mac_provider.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/mac_ether.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/sysmacros.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/dditypes.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/ddi.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/sunddi.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/miiregs.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/byteorder.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/note.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include <sys/vlan.h>
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include "vr.h"
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#include "vr_impl.h"
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * VR in a nutshell
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The card uses two rings of data structures to communicate with the host.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * These are referred to as "descriptor rings" and there is one for transmit
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * (TX) and one for receive (RX).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The driver uses a "DMA buffer" data type for mapping to those descriptor
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * rings. This is a structure with handles and a DMA'able buffer attached to it.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Receive
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The receive ring is filled with DMA buffers. Received packets are copied into
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * a newly allocated mblk's and passed upstream.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Transmit
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Each transmit descriptor has a DMA buffer attached to it. The data of TX
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * packets is copied into the DMA buffer which is then enqueued for
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * transmission.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Reclaim of transmitted packets is done as a result of a transmit completion
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * interrupt which is generated 3 times per ring at minimum.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#if defined(DEBUG)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersuint32_t vrdebug = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#define VR_DEBUG(args) do { \
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrdebug > 0) \
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (*vr_debug()) args; \
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders _NOTE(CONSTANTCONDITION) \
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while (0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_prt(const char *fmt, ...);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders void (*vr_debug())(const char *fmt, ...);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#define VR_DEBUG(args) do ; _NOTE(CONSTANTCONDITION) while (0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#endif
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.comstatic char vr_ident[] = "VIA Rhine Ethernet";
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Attributes for accessing registers and memory descriptors for this device.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic ddi_device_acc_attr_t vr_dev_dma_accattr = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DEVICE_ATTR_V0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_STRUCTURE_LE_ACC,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_STRICTORDER_ACC
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Attributes for accessing data.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic ddi_device_acc_attr_t vr_data_dma_accattr = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DEVICE_ATTR_V0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_NEVERSWAP_ACC,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_STRICTORDER_ACC
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * DMA attributes for descriptors for communication with the device
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This driver assumes that all descriptors of one ring fit in one consequitive
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * memory area of max 4K (256 descriptors) that does not cross a page boundary.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Therefore, we request 4K alignement.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic ddi_dma_attr_t vr_dev_dma_attr = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DMA_ATTR_V0, /* version number */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0, /* low DMA address range */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* high DMA address range */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x7FFFFFFF, /* DMA counter register */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x1000, /* DMA address alignment */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x7F, /* DMA burstsizes */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* min effective DMA size */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* max DMA xfer size */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* segment boundary */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* s/g list length */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* granularity of device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0 /* DMA transfer flags */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * DMA attributes for the data moved to/from the device
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Note that the alignement is set to 2K so hat a 1500 byte packet never
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * crosses a page boundary and thus that a DMA transfer is not split up in
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * multiple cookies with a 4K/8K pagesize
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic ddi_dma_attr_t vr_data_dma_attr = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DMA_ATTR_V0, /* version number */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0, /* low DMA address range */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* high DMA address range */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x7FFFFFFF, /* DMA counter register */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x800, /* DMA address alignment */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xfff, /* DMA burstsizes */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* min effective DMA size */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* max DMA xfer size */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0xFFFFFFFF, /* segment boundary */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* s/g list length */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* granularity of device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0 /* DMA transfer flags */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic mac_callbacks_t vr_mac_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_SETPROP|MC_GETPROP|MC_PROPINFO, /* Which callbacks are set */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_getstat, /* Get the value of a statistic */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_start, /* Start the device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_stop, /* Stop the device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_set_promisc, /* Enable or disable promiscuous mode */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_set_multicast, /* Enable or disable a multicast addr */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_set_ether_addr, /* Set the unicast MAC address */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_tx_enqueue_list, /* Transmit a packet */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL, /* Process an unknown ioctl */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL, /* Get capability information */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL, /* Open the device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL, /* Close the device */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_mac_setprop, /* Set properties of the device */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer vr_mac_getprop, /* Get properties of the device */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer vr_mac_propinfo /* Get properties attributes */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Table with bugs and features for each incarnation of the card.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic const chip_info_t vr_chip_info [] = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x0, 0x0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA Rhine Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NO_MEMIO),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_NONE)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x04, 0x21,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT86C100A Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NEEDMODE2PCEROPT | VR_BUG_NO_TXQUEUEING |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_BUG_NEEDMODE10T | VR_BUG_TXALIGN | VR_BUG_NO_MEMIO |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_BUG_MIIPOLLSTOP),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_NONE)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x40, 0x41,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6102-A Rhine II Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NEEDMODE2PCEROPT),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x42, 0x7f,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6102-C Rhine II Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NEEDMODE2PCEROPT),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x80, 0x82,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6105-A Rhine III Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x83, 0x89,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6105-B Rhine III Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x8a, 0x8b,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6105-LOM Rhine III Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x8c, 0x8c,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6107-A0 Rhine III Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x8d, 0x8f,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6107-A1 Rhine III Fast Ethernet",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_MRDLNMULTIPLE)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x90, 0x93,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6105M-A0 Rhine III Fast Ethernet Management Adapter",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_TXCHKSUM | VR_FEATURE_RXCHKSUM |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_CAMSUPPORT | VR_FEATURE_VLANTAGGING |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_MIBCOUNTER)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders },
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0x94, 0xff,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "VIA VT6105M-B1 Rhine III Fast Ethernet Management Adapter",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_BUG_NONE),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (VR_FEATURE_RX_PAUSE_CAP | VR_FEATURE_TX_PAUSE_CAP |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_TXCHKSUM | VR_FEATURE_RXCHKSUM |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_CAMSUPPORT | VR_FEATURE_VLANTAGGING |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FEATURE_MIBCOUNTER)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Function prototypes
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_add_intr(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_remove_intr(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int32_t vr_cam_index(vr_t *vrp, const uint8_t *maddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic uint32_t ether_crc_be(const uint8_t *address);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_tx_enqueue_msg(vr_t *vrp, mblk_t *mp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_log(vr_t *vrp, int level, const char *fmt, ...);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int vr_resume(dev_info_t *devinfo);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int vr_suspend(dev_info_t *devinfo);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_bus_config(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_bus_unconfig(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_reset(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int vr_start(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int vr_stop(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_rings_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_rings_fini(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_alloc_ring(vr_t *vrp, vr_ring_t *r, size_t n);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_free_ring(vr_ring_t *r, size_t n);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_rxring_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_rxring_fini(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_txring_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_txring_fini(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t vr_alloc_dmabuf(vr_t *vrp, vr_data_dma_t *dmap,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t flags);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_free_dmabuf(vr_data_dma_t *dmap);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_param_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic mblk_t *vr_receive(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_tx_reclaim(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_periodic(void *p);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_error(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_phy_read(vr_t *vrp, int offset, uint16_t *value);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_phy_write(vr_t *vrp, int offset, uint16_t value);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_phy_autopoll_disable(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_phy_autopoll_enable(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_link_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_link_state(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_kstats_init(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int vr_update_kstats(kstat_t *ksp, int access);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void vr_remove_kstats(vr_t *vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_register_t *macreg;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (cmd == DDI_RESUME)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (vr_resume(devinfo));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (cmd != DDI_ATTACH)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Attach.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = kmem_zalloc(sizeof (vr_t), KM_SLEEP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_set_driver_private(devinfo, vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->devinfo = devinfo;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store the name+instance of the module.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) snprintf(vrp->ifname, sizeof (vrp->ifname), "%s%d",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MODULENAME, ddi_get_instance(devinfo));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Bus initialization.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_bus_config(vrp) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "vr_bus_config failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize default parameters.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_param_init(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Setup the descriptor rings.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_rings_init(vrp) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "vr_rings_init failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize kstats.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_kstats_init(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add interrupt to the OS.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_add_intr(vrp) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "vr_add_intr failed in attach");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail3;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add mutexes.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_init(&vrp->intrlock, NULL, MUTEX_DRIVER,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_INTR_PRI(vrp->intr_pri));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_init(&vrp->oplock, NULL, MUTEX_DRIVER, NULL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_init(&vrp->tx.lock, NULL, MUTEX_DRIVER, NULL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable interrupt.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_enable(vrp->intr_hdl) != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_enable failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail5;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Register with parent, mac.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((macreg = mac_alloc(MAC_VERSION)) == NULL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "mac_alloc failed in attach");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail6;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_driver = vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_dip = devinfo;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_src_addr = vrp->vendor_ether_addr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_callbacks = &vr_mac_callbacks;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_min_sdu = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_max_sdu = ETHERMTU;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders macreg->m_margin = VLAN_TAGSZ;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (mac_register(macreg, &vrp->machdl) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "mac_register failed in attach");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders goto fail7;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_free(macreg);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail7:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_free(macreg);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail6:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_intr_disable(vrp->intr_hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail5:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_remove_intr(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail3:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_remove_kstats(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail2:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_rings_fini(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail1:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_bus_unconfig(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersfail0:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(vrp, sizeof (vr_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = ddi_get_driver_private(devinfo);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (cmd == DDI_SUSPEND)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (vr_suspend(devinfo));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (cmd != DDI_DETACH)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.state == CHIPSTATE_RUNNING)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Try to un-register from the MAC layer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (mac_unregister(vrp->machdl) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_intr_disable(vrp->intr_hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_remove_intr(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_remove_kstats(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_rings_fini(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_bus_unconfig(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(vrp, sizeof (vr_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * quiesce the card for fast reboot.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_quiesce(dev_info_t *dev_info)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)ddi_get_driver_private(dev_info);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop interrupts.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_ICR0, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_ICR1, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop DMA.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0, VR_CTRL0_DMA_STOP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add an interrupt for our device to the OS.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_add_intr(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int nintrs;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_intr_alloc(vrp->devinfo, &vrp->intr_hdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_INTR_TYPE_FIXED, /* type */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0, /* number */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 1, /* count */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &nintrs, /* actualp */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_INTR_ALLOC_STRICT);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_alloc failed: %d", rc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_intr_add_handler(vrp->intr_hdl, vr_intr, vrp, NULL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_add_handler failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_free(vrp->intr_hdl) != DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_free failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_intr_get_pri(vrp->intr_hdl, &vrp->intr_pri);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_get_pri failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_remove_handler(vrp->intr_hdl) != DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_remove_handler failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_free(vrp->intr_hdl) != DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_free failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Remove our interrupt from the OS.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_remove_intr(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_remove_handler(vrp->intr_hdl) != DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_remove_handler failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_intr_free(vrp->intr_hdl) != DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "ddi_intr_free failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Resume operation after suspend.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_resume(dev_info_t *devinfo)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)ddi_get_driver_private(devinfo);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.state == CHIPSTATE_SUSPENDED_RUNNING)
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki (void) vr_start(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Suspend operation.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_suspend(dev_info_t *devinfo)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)ddi_get_driver_private(devinfo);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.state == CHIPSTATE_RUNNING) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) vr_stop(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.state = CHIPSTATE_SUSPENDED_RUNNING;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initial bus- and device configuration during attach(9E).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_bus_config(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t addr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int n, nsets, rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t elem;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_regspec_t *regs;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get the reg property which describes the various access methods.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, vrp->devinfo,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders 0, "reg", (int **)&regs, &elem) != DDI_PROP_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "Can't get reg property");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nsets = (elem * sizeof (uint_t)) / sizeof (pci_regspec_t);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Setup access to all available sets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->nsets = nsets;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->regset = kmem_zalloc(nsets * sizeof (vr_acc_t), KM_SLEEP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < nsets; n++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_regs_map_setup(vrp->devinfo, n,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vrp->regset[n].addr, 0, 0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_dev_dma_accattr,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vrp->regset[n].hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "Setup of register set %d failed", n);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders while (--n >= 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_regs_map_free(&vrp->regset[n].hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(vrp->regset, nsets * sizeof (vr_acc_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_prop_free(regs);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bcopy(&regs[n], &vrp->regset[n].reg, sizeof (pci_regspec_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_prop_free(regs);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Assign type-named pointers to the register sets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < nsets; n++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders addr = vrp->regset[n].reg.pci_phys_hi & PCI_REG_ADDR_M;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (addr == PCI_ADDR_CONFIG && vrp->acc_cfg == NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_cfg = &vrp->regset[n];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (addr == PCI_ADDR_IO && vrp->acc_io == NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_io = &vrp->regset[n];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (addr == PCI_ADDR_MEM32 && vrp->acc_mem == NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_mem = &vrp->regset[n];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Assure there is one of each type.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->acc_cfg == NULL ||
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_io == NULL ||
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_mem == NULL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < nsets; n++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_regs_map_free(&vrp->regset[n].hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(vrp->regset, nsets * sizeof (vr_acc_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "Config-, I/O- and memory sets not available");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store vendor/device/revision.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.vendor = VR_GET16(vrp->acc_cfg, PCI_CONF_VENID);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.device = VR_GET16(vrp->acc_cfg, PCI_CONF_DEVID);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.revision = VR_GET16(vrp->acc_cfg, PCI_CONF_REVID);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Copy the matching chip_info_t structure.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders elem = sizeof (vr_chip_info) / sizeof (chip_info_t);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < elem; n++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.revision >= vr_chip_info[n].revmin &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.revision <= vr_chip_info[n].revmax) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bcopy((void*)&vr_chip_info[n],
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void*)&vrp->chip.info,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (chip_info_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we didn't find a chip_info_t for this card, copy the first
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * entry of the info structures. This is a generic Rhine whith no
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * bugs and no features.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.info.name == NULL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bcopy((void*)&vr_chip_info[0],
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void*) &vrp->chip.info,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (chip_info_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Tell what is found.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "pci%d,%d,%d: %s, revision 0x%0x",
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders PCI_REG_BUS_G(vrp->acc_cfg->reg.pci_phys_hi),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders PCI_REG_DEV_G(vrp->acc_cfg->reg.pci_phys_hi),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders PCI_REG_FUNC_G(vrp->acc_cfg->reg.pci_phys_hi),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.info.name,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.revision);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Assure that the device is prepared for memory space accesses
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This should be the default as the device advertises memory
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * access in it's BAR's. However, my VT6102 on a EPIA CL board doesn't
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * and thus we explicetely enable it.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_io, VR_CFGD, VR_CFGD_MMIOEN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Setup a handle for regular usage, prefer memory space accesses.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->acc_mem != NULL &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (vrp->chip.info.bugs & VR_BUG_NO_MEMIO) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_reg = vrp->acc_mem;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->acc_reg = vrp->acc_io;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store the vendor's MAC address.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < ETHERADDRL; n++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->vendor_ether_addr[n] = VR_GET8(vrp->acc_reg,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_ETHERADDR + n);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_bus_unconfig(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t n;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the register access handles.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (n = 0; n < vrp->nsets; n++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_regs_map_free(&vrp->regset[n].hdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(vrp->regset, vrp->nsets * sizeof (vr_acc_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize parameter structures.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_param_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize default link configuration parameters.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_en = VR_LINK_AUTONEG_ON;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en = 1; /* Select 802.3 autonegotiation */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |= MII_ABILITY_100BASE_T4;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |= MII_ABILITY_100BASE_TX_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |= MII_ABILITY_100BASE_TX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |= MII_ABILITY_10BASE_T_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |= MII_ABILITY_10BASE_T;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Not a PHY ability, but advertised on behalf of MAC */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore vrp->param.anadv_en |= MII_ABILITY_PAUSE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.mtu = ETHERMTU;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store the PHY identity.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_PHYIDH, &vrp->chip.mii.identh);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_PHYIDL, &vrp->chip.mii.identl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Clear incapabilities imposed by PHY in phymask.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask = vrp->param.anadv_en;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_STATUS, &vrp->chip.mii.status);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_10) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask &= ~MII_ABILITY_10BASE_T;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_10_FD) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask &= ~MII_ABILITY_10BASE_T_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_100_BASEX) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask &= ~MII_ABILITY_100BASE_TX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_100_BASEX_FD) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask &= ~MII_ABILITY_100BASE_TX_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_100_BASE_T4) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_phymask &= ~MII_ABILITY_100BASE_T4;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Clear incapabilities imposed by MAC in macmask
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Note that flowcontrol (FCS?) is never masked. All of our adapters
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * have the ability to honor incoming pause frames. Only the newer can
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * transmit pause frames. Since there's no asym flowcontrol in 100Mbit
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Ethernet, we always advertise (symmetric) pause.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_macmask = vrp->param.anadv_en;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Advertised capabilities is enabled minus incapable.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.anadv = vrp->param.anadv_en &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (vrp->param.an_phymask & vrp->param.an_macmask);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Ensure that autoneg of the PHY matches our default.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->param.an_en == VR_LINK_AUTONEG_ON)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control = MII_CONTROL_ANE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control =
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Setup the descriptor rings.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_rings_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->rx.ndesc = VR_RX_N_DESC;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.ndesc = VR_TX_N_DESC;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Create a ring for receive.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_alloc_ring(vrp, &vrp->rxring, vrp->rx.ndesc) != VR_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Create a ring for transmit.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_alloc_ring(vrp, &vrp->txring, vrp->tx.ndesc) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_ring(&vrp->rxring, vrp->rx.ndesc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->rx.ring = vrp->rxring.desc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.ring = vrp->txring.desc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_rings_fini(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_ring(&vrp->rxring, vrp->rx.ndesc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_ring(&vrp->txring, vrp->tx.ndesc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate a descriptor ring
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The number of descriptor entries must fit in a single page so that the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * whole ring fits in one consequtive space.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * i386: 4K page / 16 byte descriptor = 256 entries
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * sparc: 8K page / 16 byte descriptor = 512 entries
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_alloc_ring(vr_t *vrp, vr_ring_t *ring, size_t n)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_cookie_t desc_dma_cookie;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t desc_cookiecnt;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i, rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders size_t rbytes;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate a DMA handle for the chip descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_alloc_handle(vrp->devinfo,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_dev_dma_attr,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SLEEP,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &ring->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "ddi_dma_alloc_handle in vr_alloc_ring failed.");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate memory for the chip descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_mem_alloc(ring->handle,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders n * sizeof (vr_chip_desc_t),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_dev_dma_accattr,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_CONSISTENT,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SLEEP,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (caddr_t *)&ring->cdesc,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &rbytes,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &ring->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "ddi_dma_mem_alloc in vr_alloc_ring failed.");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&ring->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Map the descriptor memory.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_addr_bind_handle(ring->handle,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (caddr_t)ring->cdesc,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rbytes,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SLEEP,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &desc_dma_cookie,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &desc_cookiecnt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_DMA_MAPPED || desc_cookiecnt > 1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "ddi_dma_addr_bind_handle in vr_alloc_ring failed: "
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "rc = %d, cookiecnt = %d", rc, desc_cookiecnt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_mem_free(&ring->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&ring->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->cdesc_paddr = desc_dma_cookie.dmac_address;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate memory for the host descriptor ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc =
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (vr_desc_t *)kmem_zalloc(n * sizeof (vr_desc_t), KM_SLEEP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Interlink the descriptors and connect host- to chip descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < n; i++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Connect the host descriptor to a chip descriptor.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i].cdesc = &ring->cdesc[i];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store the DMA address and offset in the descriptor
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Offset is for ddi_dma_sync() and paddr is for ddi_get/-put().
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i].offset = i * sizeof (vr_chip_desc_t);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i].paddr = ring->cdesc_paddr + ring->desc[i].offset;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Link the previous descriptor to this one.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (i > 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Host */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i-1].next = &ring->desc[i];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Chip */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(ring->acchdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &ring->cdesc[i-1].next,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i].paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Make rings out of this list by pointing last to first.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders i = n - 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ring->desc[i].next = &ring->desc[0];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(ring->acchdl, &ring->cdesc[i].next, ring->desc[0].paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the memory allocated for a ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_free_ring(vr_ring_t *r, size_t n)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Unmap and free the chip descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_unbind_handle(r->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_mem_free(&r->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&r->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the memory for storing host descriptors
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmem_free(r->desc, n * sizeof (vr_desc_t));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize the receive ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_rxring_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i, rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_desc_t *rp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the read pointer at the start of the ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->rx.rp = &vrp->rx.ring[0];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Assign a DMA buffer to each receive descriptor.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < vrp->rx.ndesc; i++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rp = &vrp->rx.ring[i];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = vr_alloc_dmabuf(vrp,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vrp->rx.ring[i].dmabuf,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_STREAMING | DDI_DMA_READ);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders while (--i >= 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_dmabuf(&vrp->rx.ring[i].dmabuf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Store the address of the dma buffer in the chip descriptor
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->rxring.acchdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &rp->cdesc->data,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rp->dmabuf.paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Put the buffer length in the chip descriptor. Ensure that
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * length fits in the 11 bits of stat1 (2047/0x7FF)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->rxring.acchdl, &rp->cdesc->stat1,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MIN(VR_MAX_PKTSZ, rp->dmabuf.bufsz));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set descriptor ownership to the card
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->rxring.acchdl, &rp->cdesc->stat0, VR_RDES0_OWN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Sync the descriptor with main memory
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->rxring.handle, rp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t), DDI_DMA_SYNC_FORDEV);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the DMA buffers assigned to the receive ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_rxring_fini(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < vrp->rx.ndesc; i++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_dmabuf(&vrp->rx.ring[i].dmabuf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_txring_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_desc_t *wp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i, rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the write- and claim pointer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.wp = &vrp->tx.ring[0];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.cp = &vrp->tx.ring[0];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * (Re)set the TX bookkeeping.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.stallticks = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.resched = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Every transmit decreases nfree. Every reclaim increases nfree.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.nfree = vrp->tx.ndesc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Attach a DMA buffer to each transmit descriptor.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < vrp->tx.ndesc; i++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = vr_alloc_dmabuf(vrp,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vrp->tx.ring[i].dmabuf,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_STREAMING | DDI_DMA_WRITE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders while (--i >= 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_dmabuf(&vrp->tx.ring[i].dmabuf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Init & sync the TX descriptors so the device sees a valid ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < vrp->tx.ndesc; i++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders wp = &vrp->tx.ring[i];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->stat0, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->stat1, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->data,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders wp->dmabuf.paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->txring.handle, wp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SYNC_FORDEV);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the DMA buffers attached to the TX ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_txring_fini(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free the DMA buffers attached to the TX ring
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < vrp->tx.ndesc; i++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_free_dmabuf(&vrp->tx.ring[i].dmabuf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate a DMA buffer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic vr_result_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_alloc_dmabuf(vr_t *vrp, vr_data_dma_t *dmap, uint_t dmaflags)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_cookie_t dma_cookie;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t cookiecnt;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate a DMA handle for the buffer
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_alloc_handle(vrp->devinfo,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_data_dma_attr,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_DONTWAIT, NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &dmap->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "ddi_dma_alloc_handle failed in vr_alloc_dmabuf");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate the buffer
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The allocated buffer is aligned on 2K boundary. This ensures that
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * a 1500 byte frame never cross a page boundary and thus that the DMA
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * mapping can be established in 1 fragment.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_mem_alloc(dmap->handle,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_DMABUFSZ,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_data_dma_accattr,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_RDWR | DDI_DMA_STREAMING,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_DONTWAIT, NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &dmap->buf,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &dmap->bufsz,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &dmap->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "ddi_dma_mem_alloc failed in vr_alloc_dmabuf");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&dmap->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Map the memory
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = ddi_dma_addr_bind_handle(dmap->handle,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (caddr_t)dmap->buf,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dmap->bufsz,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dmaflags,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_DONTWAIT,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders NULL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &dma_cookie,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &cookiecnt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The cookiecount should never > 1 because we requested 2K alignment
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (rc != DDI_DMA_MAPPED || cookiecnt > 1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "dma_addr_bind_handle failed in vr_alloc_dmabuf: "
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "rc = %d, cookiecnt = %d", rc, cookiecnt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_mem_free(&dmap->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&dmap->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_FAILURE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dmap->paddr = dma_cookie.dmac_address;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (VR_SUCCESS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Destroy a DMA buffer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_free_dmabuf(vr_data_dma_t *dmap)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_unbind_handle(dmap->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_mem_free(&dmap->acchdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_dma_free_handle(&dmap->handle);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Interrupt service routine
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * When our vector is shared with another device, av_dispatch_autovect calls
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * all service routines for the vector until *none* of them return claimed
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * That means that, when sharing vectors, this routine is called at least
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * twice for each interrupt.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersuint_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_intr(caddr_t arg1, caddr_t arg2)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint16_t status;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mblk_t *lp = NULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t tx_resched;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t link_change;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders tx_resched = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders link_change = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (void *)arg1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders _NOTE(ARGUNUSED(arg2))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com mutex_enter(&vrp->intrlock);
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com /*
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com * If the driver is not in running state it is not our interrupt.
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com * Shared interrupts can end up here without us being started.
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com */
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com if (vrp->chip.state != CHIPSTATE_RUNNING) {
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com mutex_exit(&vrp->intrlock);
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com return (DDI_INTR_UNCLAIMED);
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com }
5815e35bec16e886bfd73f1badb4cc85ddcda92ejoostmnl@gmail.com
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Read the status register to see if the interrupt is from our device
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This read also ensures that posted writes are brought to main memory.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status = VR_GET16(vrp->acc_reg, VR_ISR0) & VR_ICR0_CFG;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (status == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Status contains no configured interrupts
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The interrupt was not generated by our device.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.intr_unclaimed++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_INTR_UNCLAIMED);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.intr_claimed++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Acknowledge the event(s) that caused interruption.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_ISR0, status);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Receive completion.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((status & (VR_ISR0_RX_DONE | VR_ISR_RX_ERR_BITS)) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Received some packets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders lp = vr_receive(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * DMA stops after a conflict in the FIFO.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((status & VR_ISR_RX_ERR_BITS) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0, VR_CTRL0_DMA_GO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status &= ~(VR_ISR0_RX_DONE | VR_ISR_RX_ERR_BITS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Transmit completion.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((status & (VR_ISR0_TX_DONE | VR_ISR_TX_ERR_BITS)) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Card done with transmitting some packets
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * TX_DONE is generated 3 times per ring but it appears
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * more often because it is also set when an RX_DONE
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * interrupt is generated.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_tx_reclaim(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders tx_resched = vrp->tx.resched;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.resched = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status &= ~(VR_ISR0_TX_DONE | VR_ISR_TX_ERR_BITS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Link status change.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((status & VR_ICR0_LINKSTATUS) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get new link state and inform the mac layer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_link_state(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status &= ~VR_ICR0_LINKSTATUS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.linkchanges++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders link_change = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Bus error.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((status & VR_ISR0_BUSERR) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "bus error occured");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->reset = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status &= ~VR_ISR0_BUSERR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * We must have handled all things here.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(status == 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Reset the device if requested
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The request can come from the periodic tx check or from the interrupt
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * status.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->reset != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_error(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->reset = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Pass up the list with received packets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (lp != NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_rx(vrp->machdl, 0, lp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Inform the upper layer on the linkstatus if there was a change.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (link_change != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_link_update(vrp->machdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (link_state_t)vrp->chip.link.state);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Restart transmissions if we were waiting for tx descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (tx_resched == 1)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_tx_update(vrp->machdl);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Read something from the card to ensure that all of our configuration
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * writes are delivered to the device before the interrupt is ended.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) VR_GET8(vrp->acc_reg, VR_ETHERADDR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (DDI_INTR_CLAIMED);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Respond to an unforseen situation by resetting the card and our bookkeeping.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_error(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "resetting MAC.");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) vr_stop(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_reset(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) vr_start(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.resets++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Collect received packets in a list.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic mblk_t *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_receive(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mblk_t *lp, *mp, *np;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_desc_t *rxp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_data_dma_t *dmap;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t rxstat0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t n;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders lp = NULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders n = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (rxp = vrp->rx.rp; ; rxp = rxp->next, n++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Sync the descriptor before looking at it.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->rxring.handle, rxp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t), DDI_DMA_SYNC_FORKERNEL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get the status from the descriptor.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxstat0 = ddi_get32(vrp->rxring.acchdl, &rxp->cdesc->stat0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * We're done if the descriptor is owned by the card.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_OWN) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if ((rxstat0 & VR_RDES0_RXOK) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Received a good packet
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dmap = &rxp->dmabuf;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pklen = (rxstat0 >> 16) - ETHERFCSL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Sync the data.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(dmap->handle, 0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pklen, DDI_DMA_SYNC_FORKERNEL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Send a new copied message upstream.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders np = allocb(pklen, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (np != NULL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bcopy(dmap->buf, np->b_rptr, pklen);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders np->b_wptr = np->b_rptr + pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_ipackets++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_rbytes += pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_BAR) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_brdcstrcv++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if ((rxstat0 & VR_RDES0_MAR) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_multircv++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Link this packet in the list.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders np->b_next = NULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (lp == NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders lp = mp = np;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mp->b_next = np;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mp = np;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.allocbfail++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_norcvbuf++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Received with errors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_ierrors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_FAE) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_align_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_CRCERR) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_fcs_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_LONG) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_toolong_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_RUNT) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_tooshort_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((rxstat0 & VR_RDES0_FOV) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_overflows++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Reset descriptor ownership to the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->rxring.acchdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &rxp->cdesc->stat0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_RDES0_OWN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->rxring.handle,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SYNC_FORDEV);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->rx.rp = rxp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we do flowcontrol and if the card can transmit pause frames,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * increment the "available receive descriptors" register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (n > 0 && vrp->chip.link.flowctrl == VR_PAUSE_BIDIRECTIONAL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Whenever the card moves a fragment to host memory it
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * decrements the RXBUFCOUNT register. If the value in the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * register reaches a low watermark, the card transmits a pause
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * frame. If the value in this register reaches a high
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * watermark, the card sends a "cancel pause" frame
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Non-zero values written to this byte register are added
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * by the chip to the register's contents, so we must write
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * the number of descriptors free'd.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_FCR0_RXBUFCOUNT, MIN(n, 0xFF));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (lp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enqueue a list of packets for transmission
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Return the packets not transmitted.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersmblk_t *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_tx_enqueue_list(void *p, mblk_t *mp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mblk_t *nextp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->tx.nfree == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_defer_xmts++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.resched = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nextp = mp->b_next;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mp->b_next = mp->b_prev = NULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_tx_enqueue_msg(vrp, mp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mp = nextp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.nfree--;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while (mp != NULL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Tell the chip to poll the TX ring.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0, VR_CTRL0_DMA_GO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (mp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enqueue a message for transmission.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_tx_enqueue_msg(vr_t *vrp, mblk_t *mp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_desc_t *wp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_data_dma_t *dmap;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t nextp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int padlen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((uchar_t)mp->b_rptr[0] == 0xff &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (uchar_t)mp->b_rptr[1] == 0xff &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (uchar_t)mp->b_rptr[2] == 0xff &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (uchar_t)mp->b_rptr[3] == 0xff &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (uchar_t)mp->b_rptr[4] == 0xff &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (uchar_t)mp->b_rptr[5] == 0xff)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_brdcstxmt++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if ((uchar_t)mp->b_rptr[0] == 1)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_multixmt++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pklen = msgsize(mp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders wp = vrp->tx.wp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dmap = &wp->dmabuf;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Copy the message into the pre-mapped buffer and free mp
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mcopymsg(mp, dmap->buf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Clean padlen bytes of short packet.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders padlen = ETHERMIN - pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (padlen > 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bzero(dmap->buf + pklen, padlen);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pklen += padlen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Most of the statistics are updated on reclaim, after the actual
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * transmit. obytes is maintained here because the length is cleared
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * after transmission
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_obytes += pklen;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Sync the data so the device sees the new content too.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(dmap->handle, 0, pklen, DDI_DMA_SYNC_FORDEV);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we have reached the TX interrupt distance, enable a TX interrupt
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * for this packet. The Interrupt Control (IC) bit in the transmit
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * descriptor doesn't have any effect on the interrupt generation
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * despite the vague statements in the datasheet. Thus, we use the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * more obscure interrupt suppress bit which is probably part of the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * MAC's bookkeeping for TX interrupts and fragmented packets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.intr_distance++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nextp = ddi_get32(vrp->txring.acchdl, &wp->cdesc->next);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->tx.intr_distance >= VR_TX_MAX_INTR_DISTANCE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Don't suppress the interrupt for this packet.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.intr_distance = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nextp &= (~VR_TDES3_SUPPRESS_INTR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Suppress the interrupt for this packet.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nextp |= VR_TDES3_SUPPRESS_INTR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write and sync the chip's descriptor
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->stat1,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pklen | (VR_TDES1_STP | VR_TDES1_EDP | VR_TDES1_CHN));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->next, nextp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_put32(vrp->txring.acchdl, &wp->cdesc->stat0, VR_TDES0_OWN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->txring.handle, wp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t), DDI_DMA_SYNC_FORDEV);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The ticks counter is cleared by reclaim when it reclaimed some
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * descriptors and incremented by the periodic TX stall check.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.stallticks = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.wp = wp->next;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Free transmitted descriptors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_tx_reclaim(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_desc_t *cp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t stat0, stat1, freed, dirty;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(&vrp->tx.lock));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders freed = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dirty = vrp->tx.ndesc - vrp->tx.nfree;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (cp = vrp->tx.cp; dirty > 0; cp = cp->next) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Sync & get descriptor status.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) ddi_dma_sync(vrp->txring.handle, cp->offset,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders sizeof (vr_chip_desc_t),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders DDI_DMA_SYNC_FORKERNEL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders stat0 = ddi_get32(vrp->txring.acchdl, &cp->cdesc->stat0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_OWN) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Do stats for the first descriptor in a chain.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders stat1 = ddi_get32(vrp->txring.acchdl, &cp->cdesc->stat1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat1 & VR_TDES1_STP) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_TERR) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_macxmt_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_UDF) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_underflows++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_ABT) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp-> stats.ether_stat_ex_collisions++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Abort and FIFO underflow stop the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packet queueing must be disabled with HD
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * links because otherwise the MAC is also lost
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * after a few of these events.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CTRL0_DMA_GO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_opackets++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_COL) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_NCR) == 1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ether_stat_first_collisions++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ether_stat_multi_collisions++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_collisions +=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (stat0 & VR_TDES0_NCR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_CRS) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_carrier_errors++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((stat0 & VR_TDES0_OWC) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_tx_late_collisions++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders freed += 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders dirty -= 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.cp = cp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (freed > 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.nfree += freed;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.stallticks = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.txreclaims += 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.txreclaim0 += 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Check TX health every 2 seconds.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_periodic(void *p)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.state == CHIPSTATE_RUNNING &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.state == VR_LINK_STATE_UP && vrp->reset == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (mutex_tryenter(&vrp->intrlock) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->tx.resched == 1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->tx.stallticks >= VR_MAXTXCHECKS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * No succesful reclaim in the last n
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * intervals. Reset the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->reset = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "TX stalled, resetting MAC");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.txstalls++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Increase until we find that we've
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * waited long enough.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->tx.stallticks += 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.txchecks++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.cyclics++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Bring the device to our desired initial state.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_reset(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t time;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Reset the MAC
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we don't wait long enough for the forced reset to complete,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * MAC looses sync with PHY. Result link up, no link change interrupt
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * and no data transfer.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_io, VR_CTRL1, VR_CTRL1_RESET);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(100);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += 100;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= 100000) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_io, VR_MISC1, VR_MISC1_RESET);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders delay(drv_usectohz(200000));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((VR_GET8(vrp->acc_io, VR_CTRL1) & VR_CTRL1_RESET) != 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders delay(drv_usectohz(10000));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Load the PROM contents into the MAC again.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_io, VR_PROMCTL, VR_PROMCTL_RELOAD);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders delay(drv_usectohz(100000));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Tell the MAC via IO space that we like to use memory space for
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * accessing registers.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_io, VR_CFGD, VR_CFGD_MMIOEN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Prepare and enable the card (MAC + PHY + PCI).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_start(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint8_t pci_latency, pci_mode;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(&vrp->oplock));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate DMA buffers for RX.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_rxring_init(vrp) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "vr_rxring_init() failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOMEM);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Allocate DMA buffers for TX.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vr_txring_init(vrp) != VR_SUCCESS) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "vr_txring_init() failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_rxring_fini(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOMEM);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Changes of the chip specific registers as done in VIA's fet driver
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * These bits are not in the datasheet and controlled by vr_chip_info.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode = VR_GET8(vrp->acc_reg, VR_MODE2);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.bugs & VR_BUG_NEEDMODE10T) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode |= VR_MODE2_MODE10T;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.bugs & VR_BUG_NEEDMODE2PCEROPT) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode |= VR_MODE2_PCEROPT;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_MRDLNMULTIPLE) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode |= VR_MODE2_MRDPL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MODE2, pci_mode);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode = VR_GET8(vrp->acc_reg, VR_MODE3);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.bugs & VR_BUG_NEEDMIION) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_mode |= VR_MODE3_MIION;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MODE3, pci_mode);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * RX: Accept broadcast packets.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_RXCFG, VR_RXCFG_ACCEPTBROAD);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * RX: Start DMA when there are 256 bytes in the FIFO.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_RXCFG, VR_RXCFG_FIFO_THRESHOLD_BITS,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_RXCFG_FIFO_THRESHOLD_256);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_BCR0, VR_BCR0_RX_FIFO_THRESHOLD_BITS,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_BCR0_RX_FIFO_THRESHOLD_256);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * TX: Start transmit when there are 256 bytes in the FIFO.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_TXCFG, VR_TXCFG_FIFO_THRESHOLD_BITS,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_TXCFG_FIFO_THRESHOLD_256);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_BCR1, VR_BCR1_TX_FIFO_THRESHOLD_BITS,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_BCR1_TX_FIFO_THRESHOLD_256);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Burst transfers up to 256 bytes.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_BCR0, VR_BCR0_DMABITS, VR_BCR0_DMA256);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Disable TX autopolling as it is bad for RX performance
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * I assume this is because the RX process finds the bus often occupied
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * by the polling process.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_CTRL1, VR_CTRL1_NOAUTOPOLL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Honor the PCI latency timer if it is reasonable.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders pci_latency = VR_GET8(vrp->acc_cfg, PCI_CONF_LATENCY_TIMER);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (pci_latency != 0 && pci_latency != 0xFF)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_CFGB, VR_CFGB_LATENCYTIMER);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_CFGB, VR_CFGB_LATENCYTIMER);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Ensure that VLAN filtering is off, because this strips the tag.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_VLANTAGGING) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_BCR1, VR_BCR1_VLANFILTER);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_TXCFG, VR_TXCFG_8021PQ_EN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Clear the CAM filter.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_CAMSUPPORT) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_ENABLE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_CAM_MASK, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_DONE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_ENABLE|VR_CAM_CTRL_SELECT_VLAN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_VCAM0, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_VCAM1, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_WRITE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_CAM_MASK, 1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(2);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_DONE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Give the start addresses of the descriptor rings to the DMA
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * controller on the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_RXADDR, vrp->rx.rp->paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_TXADDR, vrp->tx.wp->paddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * We don't use the additionally invented interrupt ICR1 register,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * so make sure these are disabled.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_ISR1, 0xFF);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_ICR1, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable interrupts.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_ISR0, 0xFFFF);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_ICR0, VR_ICR0_CFG);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable the DMA controller.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0, VR_CTRL0_DMA_GO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Configure the link. Rely on the link change interrupt for getting
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * the link state into the driver.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_link_init(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the software view on the state to 'running'.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.state = CHIPSTATE_RUNNING;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop DMA and interrupts.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_stop(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(&vrp->oplock));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop interrupts.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_ICR0, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_ICR1, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop DMA.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CTRL0, VR_CTRL0_DMA_STOP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the software view on the state to stopped.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.state = CHIPSTATE_STOPPED;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Remove DMA buffers from the rings.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_rxring_fini(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_txring_fini(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_start(void *p)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int rc;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Reset the card.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_reset(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Prepare and enable the card.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rc = vr_start(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Configure a cyclic function to keep the card & driver from diverting.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->periodic_id =
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_periodic_add(vr_periodic, vrp, VR_CHECK_INTERVAL, DDI_IPL_0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (rc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvoid
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_stop(void *p)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp = p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Stop the device.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) vr_stop(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Remove the cyclic from the system.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ddi_periodic_delete(vrp->periodic_id);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add or remove a multicast address to/from the filter
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * From the 21143 manual:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The 21143 can store 512 bits serving as hash bucket heads, and one physical
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * 48-bit Ethernet address. Incoming frames with multicast destination
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * addresses are subjected to imperfect filtering. Frames with physical
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * destination addresses are checked against the single physical address.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * For any incoming frame with a multicast destination address, the 21143
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * applies the standard Ethernet cyclic redundancy check (CRC) function to the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * first 6 bytes containing the destination address, then it uses the most
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * significant 9 bits of the result as a bit index into the table. If the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * indexed bit is set, the frame is accepted. If the bit is cleared, the frame
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * is rejected. This filtering mode is called imperfect because multicast
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * frames not addressed to this station may slip through, but it still
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * decreases the number of frames that the host can receive.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * I assume the above is also the way the VIA chips work. There's not a single
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * word about the multicast filter in the datasheet.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Another word on the CAM filter on VT6105M controllers:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The VT6105M has content addressable memory which can be used for perfect
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * filtering of 32 multicast addresses and a few VLAN id's
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * I think it works like this: When the controller receives a multicast
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * address, it looks up the address using CAM. When it is found, it takes the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * matching cell address (index) and compares this to the bit position in the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * cam mask. If the bit is set, the packet is passed up. If CAM lookup does not
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * result in a match, the packet is filtered using the hash based filter,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * if that matches, the packet is passed up and dropped otherwise
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Also, there's not a single word in the datasheet on how this cam is supposed
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * to work ...
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_set_multicast(void *p, boolean_t add, const uint8_t *mca)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t crc_index;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int32_t cam_index;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t cam_mask;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders boolean_t use_hash_filter;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ether_addr_t taddr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t a;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders use_hash_filter = B_FALSE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_CAMSUPPORT) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Program the perfect filter.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cam_mask = VR_GET32(vrp->acc_reg, VR_CAM_MASK);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (add == B_TRUE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get index of first empty slot.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bzero(&taddr, sizeof (taddr));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cam_index = vr_cam_index(vrp, taddr);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (cam_index != -1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add address at cam_index.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cam_mask |= (1 << cam_index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_ENABLE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_ADDR, cam_index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_CAM_MASK, cam_mask);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (a = 0; a < ETHERADDRL; a++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_MCAM0 + a, mca[a]);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_WRITE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(2);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_DONE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * No free CAM slots available
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Add mca to the imperfect filter.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders use_hash_filter = B_TRUE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Find the index of the entry to remove
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If the entry was not found (-1), the addition was
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * probably done when the table was full.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cam_index = vr_cam_index(vrp, mca);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (cam_index != -1) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Disable the corresponding mask bit.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cam_mask &= ~(1 << cam_index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_ENABLE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_CAM_MASK, cam_mask);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CAM_CTRL_DONE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The entry to be removed was not found
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The likely cause is that the CAM was full
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * during addition. The entry is added to the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * hash filter in that case and needs to be
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * removed there too.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders use_hash_filter = B_TRUE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * No CAM in the MAC, thus we need the hash filter.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders use_hash_filter = B_TRUE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (use_hash_filter == B_TRUE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get the CRC-32 of the multicast address
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The card uses the "MSB first" direction when calculating the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * the CRC. This is odd because ethernet is "LSB first"
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * We have to use that "big endian" approach as well.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders crc_index = ether_crc_be(mca) >> (32 - 6);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (add == B_TRUE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn bit[crc_index] on.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (crc_index < 32)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mhash0 |= (1 << crc_index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mhash1 |= (1 << (crc_index - 32));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn bit[crc_index] off.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (crc_index < 32)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mhash0 &= ~(0 << crc_index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mhash1 &= ~(0 << (crc_index - 32));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * When not promiscuous write the filter now. When promiscuous,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * the filter is open and will be written when promiscuous ends.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->promisc == B_FALSE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR0, vrp->mhash0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR1, vrp->mhash1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable/disable multicast receivements based on mcount.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (add == B_TRUE)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mcount++;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (vrp->mcount != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->mcount --;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->mcount != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_RXCFG, VR_RXCFG_ACCEPTMULTI);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_RXCFG, VR_RXCFG_ACCEPTMULTI);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Calculate the CRC32 for 6 bytes of multicast address in MSB(it) first order.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The MSB first order is a bit odd because Ethernet standard is LSB first
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic uint32_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersether_crc_be(const uint8_t *data)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t crc = (uint32_t)0xFFFFFFFFU;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t carry;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t bit;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t length;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint8_t c;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (length = 0; length < ETHERADDRL; length++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders c = data[length];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (bit = 0; bit < 8; bit++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders crc <<= 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders c >>= 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (carry)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders crc = (crc ^ 0x04C11DB6) | carry;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (crc);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Return the CAM index (base 0) of maddr or -1 if maddr is not found
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If maddr is 0, return the index of an empty slot in CAM or -1 when no free
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * slots available.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int32_t
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_cam_index(vr_t *vrp, const uint8_t *maddr)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ether_addr_t taddr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int32_t index;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t mask;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t a;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders bzero(&taddr, sizeof (taddr));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Read the CAM mask from the controller.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mask = VR_GET32(vrp->acc_reg, VR_CAM_MASK);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If maddr is 0, return the first unused slot or -1 for no unused.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (bcmp(maddr, taddr, ETHERADDRL) == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Look for the first unused position in mask.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (index = 0; index < VR_CAM_SZ; index++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (((mask >> index) & 1) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (-1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Look for maddr in CAM.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (index = 0; index < VR_CAM_SZ; index++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Look at enabled entries only */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (((mask >> index) & 1) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders continue;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_ENABLE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_ADDR, index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_READ);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(2);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (a = 0; a < ETHERADDRL; a++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders taddr[a] = VR_GET8(vrp->acc_reg, VR_MCAM0 + a);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_CAM_CTRL, VR_CAM_CTRL_DONE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (bcmp(maddr, taddr, ETHERADDRL) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (index);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (-1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set promiscuous mode on or off.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_set_promisc(void *p, boolean_t promiscflag)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint8_t rxcfg;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get current receive configuration.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxcfg = VR_GET8(vrp->acc_reg, VR_RXCFG);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->promisc = promiscflag;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (promiscflag == B_TRUE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable promiscuous mode and open the multicast filter.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxcfg |= (VR_RXCFG_PROMISC | VR_RXCFG_ACCEPTMULTI);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR0, 0xffffffff);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR1, 0xffffffff);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Restore the multicast filter and disable promiscuous mode.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR0, vrp->mhash0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT32(vrp->acc_reg, VR_MAR1, vrp->mhash1);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxcfg &= ~VR_RXCFG_PROMISC;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->mcount != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders rxcfg |= VR_RXCFG_ACCEPTMULTI;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_RXCFG, rxcfg);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->tx.lock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_getstat(void *arg, uint_t stat, uint64_t *val)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint64_t v;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (void *) arg;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders switch (stat) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders default:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOTSUP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_100T4:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_ABILITY_100BASE_T4) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_100FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_ABILITY_100BASE_TX_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_100HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_ABILITY_100BASE_TX) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_10FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_ABILITY_10BASE_T_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_10HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_ABILITY_10BASE_T) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_ASMPAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.control & MII_CONTROL_ANE) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_CAP_PAUSE:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore v = (vrp->chip.mii.anadv & MII_ABILITY_PAUSE) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ADV_REMFAULT:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anadv & MII_AN_ADVERT_REMFAULT) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_ALIGN_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_align_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_100T4:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_100_BASE_T4) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_100FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_100_BASEX_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_100HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_100_BASEX) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_10FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_10_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_10HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_10) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_ASMPAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_CANAUTONEG) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_PAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 1;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CAP_REMFAULT:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_REMFAULT) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_CARRIER_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Number of times carrier was lost or never detected on a
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * transmission attempt.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_carrier_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_JABBER_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOTSUP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_DEFER_XMTS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets without collisions where first transmit attempt was
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * delayed because the medium was busy.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_defer_xmts;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_EX_COLLISIONS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Frames where excess collisions occurred on transmit, causing
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * transmit failure.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_ex_collisions;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_FCS_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets received with CRC errors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_fcs_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_FIRST_COLLISIONS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets successfully transmitted with exactly one collision.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_first_collisions;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LINK_ASMPAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LINK_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.control & MII_CONTROL_ANE) != 0 &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (vrp->chip.mii.status & MII_STATUS_ANDONE) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LINK_DUPLEX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->chip.link.duplex;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LINK_PAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->chip.link.flowctrl;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_100T4:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.lpable & MII_ABILITY_100BASE_T4) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_1000FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_1000HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_100FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.lpable & MII_ABILITY_100BASE_TX_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_100HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.lpable & MII_ABILITY_100BASE_TX) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_10FDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.lpable & MII_ABILITY_10BASE_T_FD) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_10HDX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.lpable & MII_ABILITY_10BASE_T) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_ASMPAUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.anexp & MII_AN_EXP_LPCANAN) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_CAP_PAUSE:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore v = (vrp->chip.mii.lpable & MII_ABILITY_PAUSE) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_LP_REMFAULT:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.status & MII_STATUS_REMFAULT) != 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_MACRCV_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets received with MAC errors, except align_errors,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * fcs_errors, and toolong_errors.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_macrcv_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_MACXMT_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets encountering transmit MAC failures, except carrier
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * and collision failures.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_macxmt_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_MULTI_COLLISIONS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets successfully transmitted with multiple collisions.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_multi_collisions;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_SQE_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Number of times signal quality error was reported
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This one is reported by the PHY.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOTSUP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_TOOLONG_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Packets received larger than the maximum permitted length.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_toolong_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_TOOSHORT_ERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_tooshort_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_TX_LATE_COLLISIONS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Number of times a transmit collision occurred late
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * (after 512 bit times).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_tx_late_collisions;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_XCVR_ADDR:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * MII address in the 0 to 31 range of the physical layer
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * device in use for a given Ethernet device.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->chip.phyaddr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_XCVR_ID:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * MII transceiver manufacturer and device ID.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = (vrp->chip.mii.identh << 16) | vrp->chip.mii.identl;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case ETHER_STAT_XCVR_INUSE:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->chip.link.mau;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_BRDCSTRCV:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_brdcstrcv;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_BRDCSTXMT:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_brdcstxmt;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_MULTIXMT:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_multixmt;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_COLLISIONS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_collisions;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_IERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_ierrors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_IFSPEED:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.link.speed == VR_LINK_SPEED_100MBS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 100 * 1000 * 1000;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (vrp->chip.link.speed == VR_LINK_SPEED_10MBS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 10 * 1000 * 1000;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_IPACKETS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_ipackets;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_MULTIRCV:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_multircv;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_NORCVBUF:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_norcvbuf +=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_GET16(vrp->acc_reg, VR_TALLY_MPA);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_TALLY_MPA, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_norcvbuf;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_NOXMTBUF:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_noxmtbuf;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_OBYTES:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_obytes;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_OERRORS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.ether_stat_macxmt_errors +
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.mac_stat_underflows +
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_align_errors +
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_carrier_errors +
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->stats.ether_stat_fcs_errors;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_OPACKETS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_opackets;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_RBYTES:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_rbytes;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_UNKNOWNS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Isn't this something for the MAC layer to maintain?
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (ENOTSUP);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_UNDERFLOWS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_underflows;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_STAT_OVERFLOWS:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders v = vrp->stats.mac_stat_overflows;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *val = v;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_set_ether_addr(void *p, const uint8_t *ea)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)p;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set a new station address.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < ETHERADDRL; i++)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_ETHERADDR + i, ea[i]);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->intrlock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Configure the ethernet link according to param and chip.mii.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_link_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(&vrp->oplock));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_ANE) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we do autoneg, ensure restart autoneg is ON.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |= MII_CONTROL_RSAN;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The advertisements are prepared by param_init.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_write(vrp, MII_AN_ADVERT, vrp->chip.mii.anadv);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we don't autoneg, we need speed, duplex and flowcontrol
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * to configure the link. However, dladm doesn't allow changes
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * to speed and duplex (readonly). The way this is solved
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * (ahem) is to select the highest enabled combination
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Speed and duplex should be r/w when autoneg is off.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->param.anadv_en &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_100BASE_TX_FD) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |= MII_CONTROL_100MB;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |= MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((vrp->param.anadv_en &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_100BASE_TX) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |= MII_CONTROL_100MB;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &= ~MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((vrp->param.anadv_en &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_10BASE_T_FD) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |= MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &= ~MII_CONTROL_100MB;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &= ~MII_CONTROL_100MB;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &= ~MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write the control register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_write(vrp, MII_CONTROL, vrp->chip.mii.control);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * With autoneg off we cannot rely on the link_change interrupt for
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * for getting the status into the driver.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_ANE) == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_link_state(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_link_update(vrp->machdl,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (link_state_t)vrp->chip.link.state);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get link state in the driver and configure the MAC accordingly.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_link_state(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint16_t mask;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(&vrp->oplock));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_STATUS, &vrp->chip.mii.status);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_CONTROL, &vrp->chip.mii.control);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_AN_ADVERT, &vrp->chip.mii.anadv);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_AN_LPABLE, &vrp->chip.mii.lpable);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_read(vrp, MII_AN_EXPANSION, &vrp->chip.mii.anexp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If we did autongeg, deduce the link type/speed by selecting the
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * highest common denominator.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_ANE) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mask = vrp->chip.mii.anadv & vrp->chip.mii.lpable;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((mask & MII_ABILITY_100BASE_TX_FD) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_100MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_FULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_100X;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((mask & MII_ABILITY_100BASE_T4) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_100MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_HALF;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_100T4;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((mask & MII_ABILITY_100BASE_TX) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_100MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_HALF;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_100X;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((mask & MII_ABILITY_10BASE_T_FD) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_10MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_FULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_10;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else if ((mask & MII_ABILITY_10BASE_T) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_10MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_HALF;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_10;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_UNKNOWN;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_UNKNOWN;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_UNKNOWN;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Did we negotiate pause?
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if ((mask & MII_ABILITY_PAUSE) != 0 &&
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex == VR_LINK_DUPLEX_FULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.flowctrl = VR_PAUSE_BIDIRECTIONAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.flowctrl = VR_PAUSE_NONE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Did either one detect a AN fault?
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_REMFAULT) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "AN remote fault reported by LP.");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.lpable & MII_AN_ADVERT_REMFAULT) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "AN remote fault caused for LP.");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * We didn't autoneg
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The link type is defined by the control register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_100MB) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_100MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_100X;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed = VR_LINK_SPEED_10MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.mau = VR_MAU_10;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_FDUPLEX) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_FULL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.duplex = VR_LINK_DUPLEX_HALF;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * No pause on HDX links.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.flowctrl = VR_PAUSE_NONE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the duplex mode on the MAC according to that of the PHY.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.link.duplex == VR_LINK_DUPLEX_FULL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_CTRL1, VR_CTRL1_MACFULLDUPLEX);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable packet queueing on FDX links.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.bugs & VR_BUG_NO_TXQUEUEING) == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_CFGB, VR_CFGB_QPKTDIS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_CTRL1, VR_CTRL1_MACFULLDUPLEX);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Disable packet queueing on HDX links. With queueing enabled,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * this MAC get's lost after a TX abort (too many colisions).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_CFGB, VR_CFGB_QPKTDIS);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set pause options on the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->chip.link.flowctrl == VR_PAUSE_BIDIRECTIONAL) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * All of our MAC's can receive pause frames.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_MISC0, VR_MISC0_FDXRFEN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * VT6105 and above can transmit pause frames.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_TX_PAUSE_CAP) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set the number of available receive descriptors
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Non-zero values written to this register are added
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * to the register's contents. Careful: Writing zero
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * clears the register and thus causes a (long) pause
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * request.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_FCR0_RXBUFCOUNT,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MIN(vrp->rx.ndesc, 0xFF) -
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_GET8(vrp->acc_reg,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR0_RXBUFCOUNT));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Request pause when we have 4 descs left.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_FCR1,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR1_PAUSEONBITS, VR_FCR1_PAUSEON_04);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Cancel the pause when there are 24 descriptors again.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_FCR1,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR1_PAUSEOFFBITS, VR_FCR1_PAUSEOFF_24);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Request a pause of FFFF bit-times. This long pause
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * is cancelled when the high watermark is reached.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_FCR2_PAUSE, 0xFFFF);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Enable flow control on the MAC.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_MISC0, VR_MISC0_FDXTFEN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_FCR1, VR_FCR1_FD_RX_EN |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR1_FD_TX_EN | VR_FCR1_XONXOFF_EN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn flow control OFF.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_MISC0, VR_MISC0_FDXRFEN | VR_MISC0_FDXTFEN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.features & VR_FEATURE_TX_PAUSE_CAP) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_CLRBIT8(vrp->acc_reg, VR_FCR1,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR1_FD_RX_EN | VR_FCR1_FD_TX_EN |
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_FCR1_XONXOFF_EN);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set link state.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status & MII_STATUS_LINKUP) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.state = VR_LINK_STATE_UP;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.state = VR_LINK_STATE_DOWN;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The PHY is automatically polled by the MAC once per 1024 MD clock cycles
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * MD is clocked once per 960ns so polling happens about every 1M ns, some
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * 1000 times per second
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This polling process is required for the functionality of the link change
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * interrupt. Polling process must be disabled in order to access PHY registers
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * using MDIO
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn off PHY polling so that the PHY registers can be accessed.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_phy_autopoll_disable(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t time;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint8_t miicmd, miiaddr;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Special procedure to stop the autopolling.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.info.bugs & VR_BUG_MIIPOLLSTOP) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * If polling is enabled.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders miicmd = VR_GET8(vrp->acc_reg, VR_MIICMD);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((miicmd & VR_MIICMD_MD_AUTO) != 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Wait for the end of a cycle (mdone set).
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(10);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= VR_MMI_WAITMAX) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "Timeout in "
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "disable MII polling");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += VR_MMI_WAITINCR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders miiaddr = VR_GET8(vrp->acc_reg, VR_MIIADDR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((miiaddr & VR_MIIADDR_MDONE) == 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Once paused, we can disable autopolling.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MIICMD, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn off MII polling.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MIICMD, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Wait for MIDLE in MII address register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(VR_MMI_WAITINCR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= VR_MMI_WAITMAX) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "Timeout in disable MII polling");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += VR_MMI_WAITINCR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders miiaddr = VR_GET8(vrp->acc_reg, VR_MIIADDR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((miiaddr & VR_MIIADDR_MIDLE) == 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Turn on PHY polling. PHY's registers cannot be accessed.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_phy_autopoll_enable(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t time;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MIICMD, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MIIADDR, MII_STATUS|VR_MIIADDR_MAUTO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT8(vrp->acc_reg, VR_MIICMD, VR_MIICMD_MD_AUTO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Wait for the polling process to finish.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(VR_MMI_WAITINCR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= VR_MMI_WAITMAX) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "Timeout in enable MII polling");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += VR_MMI_WAITINCR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((VR_GET8(vrp->acc_reg, VR_MIIADDR) & VR_MIIADDR_MDONE) == 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initiate a polling.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_MIIADDR, VR_MIIADDR_MAUTO);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Read a register from the PHY using MDIO.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_phy_read(vr_t *vrp, int offset, uint16_t *value)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t time;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_autopoll_disable(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write the register number to the lower 5 bits of the MII address
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_MIIADDR, VR_MIIADDR_BITS, offset);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write a READ command to the MII control register
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This bit will be cleared when the read is finished.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_MIICMD, VR_MIICMD_MD_READ);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Wait until the read is done.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(VR_MMI_WAITINCR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= VR_MMI_WAITMAX) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "Timeout in MII read command");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += VR_MMI_WAITINCR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((VR_GET8(vrp->acc_reg, VR_MIICMD) & VR_MIICMD_MD_READ) != 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders *value = VR_GET16(vrp->acc_reg, VR_MIIDATA);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_autopoll_enable(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write to a PHY's register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_phy_write(vr_t *vrp, int offset, uint16_t value)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t time;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_autopoll_disable(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write the register number to the MII address register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBITS8(vrp->acc_reg, VR_MIIADDR, VR_MIIADDR_BITS, offset);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Write the value to the data register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_PUT16(vrp->acc_reg, VR_MIIDATA, value);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Issue the WRITE command to the command register.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * This bit will be cleared when the write is finished.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_SETBIT8(vrp->acc_reg, VR_MIICMD, VR_MIICMD_MD_WRITE);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders do {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders drv_usecwait(VR_MMI_WAITINCR);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (time >= VR_MMI_WAITMAX) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_NOTE, "Timeout in MII write command");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders time += VR_MMI_WAITINCR;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } while ((VR_GET8(vrp->acc_reg, VR_MIICMD) & VR_MIICMD_MD_WRITE) != 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_phy_autopoll_enable(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Initialize and install some private kstats.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulderstypedef struct {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders char *name;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uchar_t type;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders} vr_kstat_t;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic const vr_kstat_t vr_driver_stats [] = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"allocbfail", KSTAT_DATA_INT32},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"intr_claimed", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"intr_unclaimed", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"linkchanges", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"txnfree", KSTAT_DATA_INT32},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"txstalls", KSTAT_DATA_INT32},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"resets", KSTAT_DATA_INT32},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"txreclaims", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"txreclaim0", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"cyclics", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders {"txchecks", KSTAT_DATA_INT64},
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_kstats_init(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kstat_t *ksp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders struct kstat_named *knp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int i;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int nstats;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders nstats = sizeof (vr_driver_stats) / sizeof (vr_kstat_t);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ksp = kstat_create(MODULENAME, ddi_get_instance(vrp->devinfo),
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders "driver", "net", KSTAT_TYPE_NAMED, nstats, 0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (ksp == NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_log(vrp, CE_WARN, "kstat_create failed");
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ksp->ks_update = vr_update_kstats;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ksp->ks_private = (void*) vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders knp = ksp->ks_data;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders for (i = 0; i < nstats; i++, knp++) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kstat_named_init(knp, vr_driver_stats[i].name,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_driver_stats[i].type);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kstat_install(ksp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->ksp = ksp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic int
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_update_kstats(kstat_t *ksp, int access)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders struct kstat_named *knp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)ksp->ks_private;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders knp = ksp->ks_data;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (access != KSTAT_READ)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (EACCES);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui32 = vrp->stats.allocbfail;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.intr_claimed;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.intr_unclaimed;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.linkchanges;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui32 = vrp->tx.nfree;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui32 = vrp->stats.txstalls;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui32 = vrp->stats.resets;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.txreclaims;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.txreclaim0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.cyclics;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (knp++)->value.ui64 = vrp->stats.txchecks;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (0);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Remove 'private' kstats.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_remove_kstats(vr_t *vrp)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (vrp->ksp != NULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kstat_delete(vrp->ksp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Get a property of the device/driver
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Remarks:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * - pr_val is always an integer of size pr_valsize
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * - ENABLED (EN) is what is configured via dladm
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * - ADVERTISED (ADV) is ENABLED minus constraints, like PHY/MAC capabilities
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * - DEFAULT are driver- and hardware defaults (DEFAULT is implemented as a
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * flag in pr_flags instead of MAC_PROP_DEFAULT_)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * - perm is the permission printed on ndd -get /.. \?
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t pr_valsize, void *pr_val)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t err;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint64_t val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Since we have no private properties */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders _NOTE(ARGUNUSED(pr_name))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (pr_num) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_1000FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_1000HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_1000HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.anadv &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_TX_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.anadv &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_TX) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100T4_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.anadv &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_T4) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.anadv &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_10BASE_T_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_10HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.anadv &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_10BASE_T) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_AUTONEG:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.control &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_CONTROL_ANE) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_DUPLEX:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = vrp->chip.link.duplex;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->param.anadv_en &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_TX_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->param.anadv_en &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_TX) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100T4_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->param.anadv_en &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_100BASE_T4) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_10FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->param.anadv_en &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_10BASE_T_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_10HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->param.anadv_en &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_ABILITY_10BASE_T) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_AUTONEG:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = vrp->param.an_en == VR_LINK_AUTONEG_ON;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_FLOWCTRL:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = vrp->chip.link.flowctrl;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_MTU:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = vrp->param.mtu;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_SPEED:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (vrp->chip.link.speed ==
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer VR_LINK_SPEED_100MBS)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = 100 * 1000 * 1000;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else if (vrp->chip.link.speed ==
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer VR_LINK_SPEED_10MBS)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = 10 * 1000 * 1000;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders val = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_STATUS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = vrp->chip.link.state;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer default:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer err = ENOTSUP;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (err == 0 && pr_num != MAC_PROP_PRIVATE) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pr_valsize == sizeof (uint64_t))
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *(uint64_t *)pr_val = val;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else if (pr_valsize == sizeof (uint32_t))
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *(uint32_t *)pr_val = val;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else if (pr_valsize == sizeof (uint16_t))
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *(uint16_t *)pr_val = val;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else if (pr_valsize == sizeof (uint8_t))
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *(uint8_t *)pr_val = val;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer err = EINVAL;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (err);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyervoid
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyervr_mac_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer vr_t *vrp = (vr_t *)arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint8_t val, perm;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* Since we have no private properties */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer _NOTE(ARGUNUSED(pr_name))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (pr_num) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_1000FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_1000HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_1000FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_1000HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_100T4_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_ADV_10HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_100_BASEX_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_100_BASEX) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_100T4_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_100_BASE_T4) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_10FDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_10_FD) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_10HDX_CAP:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_10) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_AUTONEG:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_EN_AUTONEG:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer val = (vrp->chip.mii.status &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_STATUS_CANAUTONEG) != 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_FLOWCTRL:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_default_link_flowctrl(prh,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer LINK_FLOWCTRL_BI);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_MTU:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_range_uint32(prh,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ETHERMTU, ETHERMTU);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_DUPLEX:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Writability depends on autoneg.
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer perm = ((vrp->chip.mii.control &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_CONTROL_ANE) == 0) ? MAC_PROP_PERM_RW :
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MAC_PROP_PERM_READ;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, perm);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (perm == MAC_PROP_PERM_RW) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_default_uint8(prh,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer VR_LINK_DUPLEX_FULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_SPEED:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer perm = ((vrp->chip.mii.control &
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MII_CONTROL_ANE) == 0) ?
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, perm);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (perm == MAC_PROP_PERM_RW) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_default_uint64(prh,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer 100 * 1000 * 1000);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_PROP_STATUS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer default:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_set_default_uint8(prh, val);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Set a property of the device.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_mac_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint_t pr_valsize, const void *pr_val)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_t *vrp;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint32_t err;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders uint64_t val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /* Since we have no private properties */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders _NOTE(ARGUNUSED(pr_name))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = 0;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp = (vr_t *)arg;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders /*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * The current set of public property values are passed as integers
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Private properties are passed as strings in pr_val length pr_valsize.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (pr_num != MAC_PROP_PRIVATE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (pr_valsize == sizeof (uint64_t))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders val = *(uint64_t *)pr_val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (pr_valsize == sizeof (uint32_t))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders val = *(uint32_t *)pr_val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (pr_valsize == sizeof (uint16_t))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders val = *(uint32_t *)pr_val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (pr_valsize == sizeof (uint8_t))
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders val = *(uint8_t *)pr_val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (EINVAL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders switch (pr_num) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_DUPLEX:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.control & MII_CONTROL_ANE) == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == LINK_DUPLEX_FULL)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (val == LINK_DUPLEX_HALF)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_CONTROL_FDUPLEX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_100FDX_CAP:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_ABILITY_100BASE_TX_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_100BASE_TX_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_100HDX_CAP:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_ABILITY_100BASE_TX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_100BASE_TX;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_100T4_CAP:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_ABILITY_100BASE_T4;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_100BASE_T4;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_10FDX_CAP:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_ABILITY_10BASE_T_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_10BASE_T_FD;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_10HDX_CAP:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en &=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ~MII_ABILITY_10BASE_T;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.anadv_en |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_ABILITY_10BASE_T;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_EN_AUTONEG:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_en = VR_LINK_AUTONEG_OFF;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control &= ~MII_CONTROL_ANE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders } else {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.an_en = VR_LINK_AUTONEG_ON;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if ((vrp->chip.mii.status &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_STATUS_CANAUTONEG) != 0)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.control |=
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MII_CONTROL_ANE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_FLOWCTRL:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == LINK_FLOWCTRL_NONE)
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore vrp->param.anadv_en &= ~MII_ABILITY_PAUSE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (val == LINK_FLOWCTRL_BI)
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore vrp->param.anadv_en |= MII_ABILITY_PAUSE;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_MTU:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val >= ETHERMIN && val <= ETHERMTU)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->param.mtu = (uint32_t)val;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders case MAC_PROP_SPEED:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (val == 10 * 1000 * 1000)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed =
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_LINK_SPEED_10MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else if (val == 100 * 1000 * 1000)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.link.speed =
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders VR_LINK_SPEED_100MBS;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = EINVAL;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders default:
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders err = ENOTSUP;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders break;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (err == 0 && pr_num != MAC_PROP_PRIVATE) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vrp->chip.mii.anadv = vrp->param.anadv_en &
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (vrp->param.an_phymask & vrp->param.an_macmask);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_link_init(vrp);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(&vrp->oplock);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (err);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders/*
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders * Logging and debug functions.
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic struct {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders kmutex_t mutex[1];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders const char *ifname;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders const char *fmt;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int level;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders} prtdata;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_vprt(const char *fmt, va_list args)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders char buf[512];
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(prtdata.mutex));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders (void) vsnprintf(buf, sizeof (buf), fmt, args);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders cmn_err(prtdata.level, prtdata.fmt, prtdata.ifname, buf);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_log(vr_t *vrp, int level, const char *fmt, ...)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_list args;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(prtdata.mutex);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.ifname = vrp->ifname;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.fmt = "!%s: %s";
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.level = level;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_start(args, fmt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_vprt(fmt, args);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_end(args);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(prtdata.mutex);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#if defined(DEBUG)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic void
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvr_prt(const char *fmt, ...)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_list args;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders ASSERT(mutex_owned(prtdata.mutex));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_start(args, fmt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_vprt(fmt, args);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders va_end(args);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_exit(prtdata.mutex);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersvoid
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders(*vr_debug())(const char *fmt, ...)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_enter(prtdata.mutex);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.ifname = MODULENAME;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.fmt = "^%s: %s\n";
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders prtdata.level = CE_CONT;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (vr_prt);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders#endif /* DEBUG */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost MuldersDDI_DEFINE_STREAM_OPS(vr_dev_ops, nulldev, nulldev, vr_attach, vr_detach,
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersnodev, NULL, D_MP, NULL, vr_quiesce);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic struct modldrv vr_modldrv = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &mod_driverops, /* Type of module. This one is a driver */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders vr_ident, /* short description */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders &vr_dev_ops /* driver specific ops */
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersstatic struct modlinkage modlinkage = {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders MODREV_1, (void *)&vr_modldrv, NULL
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders};
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders_info(struct modinfo *modinfop)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (mod_info(&modlinkage, modinfop));
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders_init(void)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int status;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_init_ops(&vr_dev_ops, MODULENAME);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status = mod_install(&modlinkage);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (status == DDI_SUCCESS)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_init(prtdata.mutex, NULL, MUTEX_DRIVER, NULL);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders else
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_fini_ops(&vr_dev_ops);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (status);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Muldersint
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders_fini(void)
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders{
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders int status;
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders status = mod_remove(&modlinkage);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders if (status == 0) {
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mac_fini_ops(&vr_dev_ops);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders mutex_destroy(prtdata.mutex);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders }
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders return (status);
2ca5b6595b95478e6568b0e77c6c83c8a870867aJoost Mulders}