--- a/exception_lists/closed-bins Thu Dec 02 20:23:12 2010 +0530
+++ b/exception_lists/closed-bins Fri Dec 03 07:32:02 2010 -0800
@@ -13,6 +13,8 @@
./etc/snmp/conf
./etc/snmp/conf/mibiisa.reg
./etc/snmp/conf/snmp.conf
+./kernel/drv/iprb
+./kernel/drv/amd64/iprb
./lib/crypto
./lib/crypto/kcfd
./lib/libc_i18n.a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkg/manifests/driver-network-iprb.mf Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,64 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# The default for payload-bearing actions in this package is to appear in the
+# global zone only. See the include file for greater detail, as well as
+# information about overriding the defaults.
+#
+<include global_zone_only_component>
+set name=pkg.fmri value=pkg:/driver/network/iprb@$(PKGVERS)
+set name=pkg.description value="Intel 8255x Fast Ethernet Driver"
+set name=pkg.summary value="Intel 8255x Fast Ethernet Driver"
+set name=info.classification \
+ value=org.opensolaris.category.2008:Drivers/Networking
+set name=variant.arch value=i386
+dir path=etc group=sys
+dir path=kernel group=sys
+dir path=kernel/drv group=sys
+dir path=kernel/drv/$(ARCH64) group=sys
+driver name=iprb clone_perms="iprb 0666 root sys" perms="* 0666 root sys" \
+ alias=pci8086,1029 \
+ alias=pci8086,1030 \
+ alias=pci8086,1031 \
+ alias=pci8086,1032 \
+ alias=pci8086,1038 \
+ alias=pci8086,1039 \
+ alias=pci8086,103d \
+ alias=pci8086,1050 \
+ alias=pci8086,1059 \
+ alias=pci8086,1068 \
+ alias=pci8086,1069 \
+ alias=pci8086,1092 \
+ alias=pci8086,1209 \
+ alias=pci8086,1229 \
+ alias=pci8086,2449 \
+ alias=pci8086,27dc
+file path=kernel/drv/$(ARCH64)/iprb group=sys
+file path=kernel/drv/iprb group=sys
+license lic_CDDL license=lic_CDDL
+license usr/src/uts/common/io/iprb/THIRDPARTYLICENSE \
+ license=usr/src/uts/common/io/iprb/THIRDPARTYLICENSE
--- a/usr/src/pkg/manifests/driver-network-platform.mf Thu Dec 02 20:23:12 2010 +0530
+++ b/usr/src/pkg/manifests/driver-network-platform.mf Fri Dec 03 07:32:02 2010 -0800
@@ -48,135 +48,14 @@
alias=pci1109,1400 \
alias=pci1109,2400 \
alias=pci2646,1
-driver name=iprb clone_perms="iprb 0666 root sys" perms="* 0666 root sys" \
- alias=pci8086,1029 \
- alias=pci8086,1030 \
- alias=pci8086,1031 \
- alias=pci8086,1032 \
- alias=pci8086,1038 \
- alias=pci8086,1039 \
- alias=pci8086,103d \
- alias=pci8086,103d.8086.103d \
- alias=pci8086,1050 \
- alias=pci8086,1050.8086.3020 \
- alias=pci8086,1050.8086.302f \
- alias=pci8086,1050.8086.3427 \
- alias=pci8086,1059 \
- alias=pci8086,1068 \
- alias=pci8086,1069 \
- alias=pci8086,1092 \
- alias=pci8086,1209 \
- alias=pci8086,1229 \
- alias=pci8086,1229.8086.1 \
- alias=pci8086,1229.8086.10 \
- alias=pci8086,1229.8086.1009 \
- alias=pci8086,1229.8086.100c \
- alias=pci8086,1229.8086.1012 \
- alias=pci8086,1229.8086.1013 \
- alias=pci8086,1229.8086.1015 \
- alias=pci8086,1229.8086.1016 \
- alias=pci8086,1229.8086.1017 \
- alias=pci8086,1229.8086.1030 \
- alias=pci8086,1229.8086.1040 \
- alias=pci8086,1229.8086.1041 \
- alias=pci8086,1229.8086.1042 \
- alias=pci8086,1229.8086.1050 \
- alias=pci8086,1229.8086.1051 \
- alias=pci8086,1229.8086.1052 \
- alias=pci8086,1229.8086.10f0 \
- alias=pci8086,1229.8086.11 \
- alias=pci8086,1229.8086.12 \
- alias=pci8086,1229.8086.1229 \
- alias=pci8086,1229.8086.13 \
- alias=pci8086,1229.8086.2 \
- alias=pci8086,1229.8086.2009 \
- alias=pci8086,1229.8086.200d \
- alias=pci8086,1229.8086.200e \
- alias=pci8086,1229.8086.200f \
- alias=pci8086,1229.8086.2010 \
- alias=pci8086,1229.8086.2013 \
- alias=pci8086,1229.8086.2016 \
- alias=pci8086,1229.8086.2017 \
- alias=pci8086,1229.8086.2018 \
- alias=pci8086,1229.8086.2019 \
- alias=pci8086,1229.8086.2101 \
- alias=pci8086,1229.8086.2102 \
- alias=pci8086,1229.8086.2103 \
- alias=pci8086,1229.8086.2104 \
- alias=pci8086,1229.8086.2105 \
- alias=pci8086,1229.8086.2106 \
- alias=pci8086,1229.8086.2107 \
- alias=pci8086,1229.8086.2108 \
- alias=pci8086,1229.8086.2200 \
- alias=pci8086,1229.8086.2201 \
- alias=pci8086,1229.8086.2202 \
- alias=pci8086,1229.8086.2203 \
- alias=pci8086,1229.8086.2204 \
- alias=pci8086,1229.8086.2205 \
- alias=pci8086,1229.8086.2206 \
- alias=pci8086,1229.8086.2207 \
- alias=pci8086,1229.8086.2208 \
- alias=pci8086,1229.8086.2402 \
- alias=pci8086,1229.8086.2407 \
- alias=pci8086,1229.8086.2408 \
- alias=pci8086,1229.8086.2409 \
- alias=pci8086,1229.8086.240f \
- alias=pci8086,1229.8086.2410 \
- alias=pci8086,1229.8086.2411 \
- alias=pci8086,1229.8086.2412 \
- alias=pci8086,1229.8086.2413 \
- alias=pci8086,1229.8086.3 \
- alias=pci8086,1229.8086.30 \
- alias=pci8086,1229.8086.3000 \
- alias=pci8086,1229.8086.3001 \
- alias=pci8086,1229.8086.3002 \
- alias=pci8086,1229.8086.3006 \
- alias=pci8086,1229.8086.3007 \
- alias=pci8086,1229.8086.3008 \
- alias=pci8086,1229.8086.3010 \
- alias=pci8086,1229.8086.3011 \
- alias=pci8086,1229.8086.3012 \
- alias=pci8086,1229.8086.301a \
- alias=pci8086,1229.8086.31 \
- alias=pci8086,1229.8086.3411 \
- alias=pci8086,1229.8086.4 \
- alias=pci8086,1229.8086.40 \
- alias=pci8086,1229.8086.41 \
- alias=pci8086,1229.8086.42 \
- alias=pci8086,1229.8086.5 \
- alias=pci8086,1229.8086.50 \
- alias=pci8086,1229.8086.6 \
- alias=pci8086,1229.8086.7 \
- alias=pci8086,1229.8086.8 \
- alias=pci8086,1229.8086.9 \
- alias=pci8086,1229.8086.a \
- alias=pci8086,1229.8086.b \
- alias=pci8086,1229.8086.c \
- alias=pci8086,1229.8086.d \
- alias=pci8086,1229.8086.e \
- alias=pci8086,1229.8086.f \
- alias=pci8086,2449 \
- alias=pci8086,2449.8086.3010 \
- alias=pci8086,2449.8086.3011 \
- alias=pci8086,2449.8086.3012 \
- alias=pci8086,2449.8086.3013 \
- alias=pci8086,2449.8086.3014 \
- alias=pci8086,2449.8086.3015 \
- alias=pci8086,2449.8086.3016 \
- alias=pci8086,2449.8086.3017 \
- alias=pci8086,2449.8086.3018 \
- alias=pci8086,27dc \
- alias=pci8086,27dc.8086.308d
driver name=pcn clone_perms="pcn 0666 root sys" perms="* 0666 root sys" \
alias=pci1022,2000 \
alias=pci103c,104c
file path=etc/bootrc group=sys mode=0755
file path=etc/mach group=sys original_name=SUNWos86r:etc/mach preserve=true
file path=kernel/drv/$(ARCH64)/dnet group=sys
-file path=kernel/drv/$(ARCH64)/iprb group=sys
file path=kernel/drv/$(ARCH64)/pcn group=sys
file path=kernel/drv/dnet group=sys
-file path=kernel/drv/iprb group=sys
file path=kernel/drv/pcn group=sys
file path=kernel/drv/sd group=sys
file path=kernel/drv/sd.conf group=sys \
@@ -185,9 +64,10 @@
name="Platform Support, OS Functionality (Root)"
license cr_Sun license=cr_Sun
license lic_CDDL license=lic_CDDL
+# when pcn is removed, we can remove the OSBL as well
license lic_OSBL license=lic_OSBL
license lic_OSBL_preamble license=lic_OSBL_preamble
-license usr/closed/uts/intel/io/iprb/THIRDPARTYLICENSE \
- license=usr/closed/uts/intel/io/iprb/THIRDPARTYLICENSE
# elxl moved out of this package, so create a dependency for upgraded systems
depend fmri=driver/network/elxl type=require
+# iprb moved out of this package, so create a dependency for upgraded systems
+depend fmri=driver/network/iprb type=require
--- a/usr/src/uts/common/Makefile.files Thu Dec 02 20:23:12 2010 +0530
+++ b/usr/src/uts/common/Makefile.files Fri Dec 03 07:32:02 2010 -0800
@@ -1900,6 +1900,11 @@
igb_rx.o igb_stat.o igb_tx.o
#
+# Intel Pro/100 NIC driver module
+#
+IPRB_OBJS = iprb.o
+
+#
# Intel 10GbE PCIE NIC driver module
#
IXGBE_OBJS = ixgbe_82598.o ixgbe_82599.o ixgbe_api.o \
--- a/usr/src/uts/common/Makefile.rules Thu Dec 02 20:23:12 2010 +0530
+++ b/usr/src/uts/common/Makefile.rules Fri Dec 03 07:32:02 2010 -0800
@@ -1303,6 +1303,10 @@
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/iprb/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/ixgbe/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -2485,6 +2489,9 @@
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/igb/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/iprb/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/ixgbe/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/iprb/THIRDPARTYLICENSE Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,28 @@
+Copyright (c) 1999-2001, Intel Corporation
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/iprb/THIRDPARTYLICENSE.descrip Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,1 @@
+INTEL 8255x CPUSAVER MICROCODE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/iprb/iprb.c Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,1796 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Intel Pro/100B Ethernet Driver
+ */
+
+#include <sys/types.h>
+#include <sys/modctl.h>
+#include <sys/conf.h>
+#include <sys/kmem.h>
+#include <sys/ksynch.h>
+#include <sys/cmn_err.h>
+#include <sys/note.h>
+#include <sys/pci.h>
+#include <sys/pci_cap.h>
+#include <sys/ethernet.h>
+#include <sys/mii.h>
+#include <sys/miiregs.h>
+#include <sys/mac.h>
+#include <sys/mac_ether.h>
+#include <sys/ethernet.h>
+#include <sys/vlan.h>
+#include <sys/list.h>
+#include <sys/sysmacros.h>
+#include <sys/varargs.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#include "iprb.h"
+#include "rcvbundl.h"
+
+/*
+ * Intel has openly documented the programming interface for these
+ * parts in the "Intel 8255x 10/100 Mbps Ethernet Controller Family
+ * Open Source Software Developer Manual".
+ *
+ * While some open source systems have utilized many of the features
+ * of some models in this family (especially scatter gather and IP
+ * checksum support), we have elected to offer only the basic
+ * functionality. These are only 10/100 parts, and the additional
+ * complexity is not justified by the minimal performance benefit.
+ * KISS. So, we are only supporting the simple 82557 features.
+ */
+
+static uint16_t iprb_mii_read(void *, uint8_t, uint8_t);
+static void iprb_mii_write(void *, uint8_t, uint8_t, uint16_t);
+static void iprb_mii_notify(void *, link_state_t);
+static int iprb_attach(dev_info_t *);
+static int iprb_detach(dev_info_t *);
+static int iprb_quiesce(dev_info_t *);
+static int iprb_suspend(dev_info_t *);
+static int iprb_resume(dev_info_t *);
+static int iprb_m_stat(void *, uint_t, uint64_t *);
+static int iprb_m_start(void *);
+static void iprb_m_stop(void *);
+static int iprb_m_promisc(void *, boolean_t);
+static int iprb_m_multicst(void *, boolean_t, const uint8_t *);
+static int iprb_m_unicst(void *, const uint8_t *);
+static mblk_t *iprb_m_tx(void *, mblk_t *);
+static void iprb_m_ioctl(void *, queue_t *, mblk_t *);
+static int iprb_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
+ const void *);
+static int iprb_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
+ void *);
+static void iprb_m_propinfo(void *, const char *, mac_prop_id_t,
+ mac_prop_info_handle_t);
+static void iprb_destroy(iprb_t *);
+static int iprb_configure(iprb_t *);
+static void iprb_eeprom_sendbits(iprb_t *, uint32_t, uint8_t);
+static uint16_t iprb_eeprom_read(iprb_t *, uint16_t);
+static void iprb_identify(iprb_t *);
+static int iprb_cmd_submit(iprb_t *, uint16_t);
+static void iprb_cmd_reclaim(iprb_t *);
+static int iprb_cmd_ready(iprb_t *);
+static int iprb_cmd_drain(iprb_t *);
+static void iprb_rx_add(iprb_t *);
+static void iprb_rx_init(iprb_t *);
+static mblk_t *iprb_rx(iprb_t *);
+static mblk_t *iprb_send(iprb_t *, mblk_t *);
+static uint_t iprb_intr(caddr_t, caddr_t);
+static void iprb_periodic(void *);
+static int iprb_add_intr(iprb_t *);
+static int iprb_dma_alloc(iprb_t *, iprb_dma_t *, size_t);
+static void iprb_dma_free(iprb_dma_t *);
+static iprb_dma_t *iprb_cmd_next(iprb_t *);
+static int iprb_set_config(iprb_t *);
+static int iprb_set_unicast(iprb_t *);
+static int iprb_set_multicast(iprb_t *);
+static int iprb_set_ucode(iprb_t *);
+static void iprb_update_stats(iprb_t *);
+static int iprb_start(iprb_t *);
+static void iprb_stop(iprb_t *);
+static int iprb_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
+static int iprb_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
+static void iprb_error(iprb_t *, const char *, ...);
+
+static mii_ops_t iprb_mii_ops = {
+ MII_OPS_VERSION,
+ iprb_mii_read,
+ iprb_mii_write,
+ iprb_mii_notify,
+ NULL, /* reset */
+};
+
+static mac_callbacks_t iprb_m_callbacks = {
+ MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
+ iprb_m_stat,
+ iprb_m_start,
+ iprb_m_stop,
+ iprb_m_promisc,
+ iprb_m_multicst,
+ iprb_m_unicst,
+ iprb_m_tx,
+ NULL,
+ iprb_m_ioctl, /* mc_ioctl */
+ NULL, /* mc_getcapab */
+ NULL, /* mc_open */
+ NULL, /* mc_close */
+ iprb_m_setprop,
+ iprb_m_getprop,
+ iprb_m_propinfo
+};
+
+
+/*
+ * Stream information
+ */
+DDI_DEFINE_STREAM_OPS(iprb_devops, nulldev, nulldev,
+ iprb_ddi_attach, iprb_ddi_detach, nodev, NULL, D_MP, NULL, iprb_quiesce);
+
+static struct modldrv iprb_modldrv = {
+ &mod_driverops, /* drv_modops */
+ "Intel 8255x Ethernet", /* drv_linkinfo */
+ &iprb_devops /* drv_dev_ops */
+};
+
+static struct modlinkage iprb_modlinkage = {
+ MODREV_1, /* ml_rev */
+ { &iprb_modldrv, NULL } /* ml_linkage */
+};
+
+
+static ddi_device_acc_attr_t acc_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+static ddi_device_acc_attr_t buf_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_STORECACHING_OK_ACC
+};
+
+/*
+ * The 8225x is a 32-bit addressing engine, but it can only address up
+ * to 31 bits on a single transaction. (Far less in reality it turns
+ * out.) Statistics buffers have to be 16-byte aligned, and as we
+ * allocate individual data pieces for other things, there is no
+ * compelling reason to use another attribute with support for less
+ * strict alignment.
+ */
+static ddi_dma_attr_t dma_attr = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* dma_attr_addr_lo */
+ 0xFFFFFFFFU, /* dma_attr_addr_hi */
+ 0x7FFFFFFFU, /* dma_attr_count_max */
+ 16, /* dma_attr_align */
+ 0x100, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ 0xFFFFFFFFU, /* dma_attr_maxxfer */
+ 0xFFFFFFFFU, /* dma_attr_seg */
+ 1, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0 /* dma_attr_flags */
+};
+
+#define DECL_UCODE(x) \
+ static const uint32_t x ## _WORDS[] = x ## _RCVBUNDLE_UCODE
+DECL_UCODE(D101_A);
+DECL_UCODE(D101_B0);
+DECL_UCODE(D101M_B);
+DECL_UCODE(D101S);
+DECL_UCODE(D102_B);
+DECL_UCODE(D102_C);
+DECL_UCODE(D102_E);
+
+static uint8_t iprb_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * We don't bother allowing for tuning of the CPU saver algorithm.
+ * The ucode has reasonable defaults built-in. However, some variants
+ * apparently have bug fixes delivered via this ucode, so we still
+ * need to support the ucode upload.
+ */
+typedef struct {
+ uint8_t rev;
+ uint8_t length;
+ const uint32_t *ucode;
+} iprb_ucode_t;
+
+#define UCODE(x) \
+ sizeof (x ## _WORDS) / sizeof (uint32_t), x ## _WORDS
+
+static const iprb_ucode_t iprb_ucode[] = {
+ { REV_82558_A4, UCODE(D101_A) },
+ { REV_82558_B0, UCODE(D101_B0) },
+ { REV_82559_A0, UCODE(D101M_B) },
+ { REV_82559S_A, UCODE(D101S) },
+ { REV_82550, UCODE(D102_B) },
+ { REV_82550_C, UCODE(D102_C) },
+ { REV_82551_F, UCODE(D102_E) },
+ { 0 },
+};
+
+int
+_init(void)
+{
+ int rv;
+ mac_init_ops(&iprb_devops, "iprb");
+ if ((rv = mod_install(&iprb_modlinkage)) != DDI_SUCCESS) {
+ mac_fini_ops(&iprb_devops);
+ }
+ return (rv);
+}
+
+int
+_fini(void)
+{
+ int rv;
+ if ((rv = mod_remove(&iprb_modlinkage)) == DDI_SUCCESS) {
+ mac_fini_ops(&iprb_devops);
+ }
+ return (rv);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&iprb_modlinkage, modinfop));
+}
+
+int
+iprb_attach(dev_info_t *dip)
+{
+ iprb_t *ip;
+ uint16_t w;
+ int i;
+ mac_register_t *macp;
+
+ ip = kmem_zalloc(sizeof (*ip), KM_SLEEP);
+ ddi_set_driver_private(dip, ip);
+ ip->dip = dip;
+
+ list_create(&ip->mcast, sizeof (struct iprb_mcast),
+ offsetof(struct iprb_mcast, node));
+
+ /* we don't support high level interrupts, so we don't need cookies */
+ mutex_init(&ip->culock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&ip->rulock, NULL, MUTEX_DRIVER, NULL);
+
+ if (pci_config_setup(dip, &ip->pcih) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to map configuration space");
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ if (ddi_regs_map_setup(dip, 1, &ip->regs, 0, 0, &acc_attr,
+ &ip->regsh) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to map device registers");
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ /* Reset, but first go into idle state */
+ PUT32(ip, CSR_PORT, PORT_SEL_RESET);
+ drv_usecwait(10);
+ PUT32(ip, CSR_PORT, PORT_SW_RESET);
+ drv_usecwait(10);
+ PUT8(ip, CSR_INTCTL, INTCTL_MASK);
+ (void) GET8(ip, CSR_INTCTL);
+
+ /*
+ * Precalculate watchdog times.
+ */
+ ip->tx_timeout = drv_usectohz(TX_WATCHDOG * 1000000);
+ ip->rx_timeout = drv_usectohz(RX_WATCHDOG * 1000000);
+
+ iprb_identify(ip);
+
+ /* Obtain our factory MAC address */
+ w = iprb_eeprom_read(ip, 0);
+ ip->factaddr[0] = w & 0xff;
+ ip->factaddr[1] = w >> 8;
+ w = iprb_eeprom_read(ip, 1);
+ ip->factaddr[2] = w & 0xff;
+ ip->factaddr[3] = w >> 8;
+ w = iprb_eeprom_read(ip, 2);
+ ip->factaddr[4] = w & 0xff;
+ ip->factaddr[5] = w >> 8;
+ bcopy(ip->factaddr, ip->curraddr, 6);
+
+ if (ip->resumebug) {
+ /*
+ * Generally, most devices we will ever see will
+ * already have fixed firmware. Since I can't verify
+ * the validity of the fix (no suitably downrev
+ * hardware), we'll just do our best to avoid it for
+ * devices that exhibit this behavior.
+ */
+ if ((iprb_eeprom_read(ip, 10) & 0x02) == 0) {
+ /* EEPROM fix was already applied, assume safe. */
+ ip->resumebug = B_FALSE;
+ }
+ }
+
+ if ((iprb_eeprom_read(ip, 3) & 0x3) != 0x3) {
+ cmn_err(CE_CONT, "?Enabling RX errata workaround.\n");
+ ip->rxhangbug = B_TRUE;
+ }
+
+ /* Determine whether we have an MII or a legacy 80c24 */
+ w = iprb_eeprom_read(ip, 6);
+ if ((w & 0x3f00) != 0x0600) {
+ if ((ip->miih = mii_alloc(ip, dip, &iprb_mii_ops)) == NULL) {
+ iprb_error(ip, "unable to allocate MII ops vector");
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+ if (ip->canpause) {
+ mii_set_pauseable(ip->miih, B_TRUE, B_FALSE);
+ }
+ }
+
+ /* Allocate cmds and tx region */
+ for (i = 0; i < NUM_TX; i++) {
+ /* Command blocks */
+ if (iprb_dma_alloc(ip, &ip->cmds[i], CB_SIZE) != DDI_SUCCESS) {
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+ }
+
+ for (i = 0; i < NUM_TX; i++) {
+ iprb_dma_t *cb = &ip->cmds[i];
+ /* Link the command blocks into a ring */
+ PUTCB32(cb, CB_LNK_OFFSET, (ip->cmds[(i + 1) % NUM_TX].paddr));
+ }
+
+ for (i = 0; i < NUM_RX; i++) {
+ /* Rx packet buffers */
+ if (iprb_dma_alloc(ip, &ip->rxb[i], RFD_SIZE) != DDI_SUCCESS) {
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+ }
+ if (iprb_dma_alloc(ip, &ip->stats, STATS_SIZE) != DDI_SUCCESS) {
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ if (iprb_add_intr(ip) != DDI_SUCCESS) {
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
+ iprb_error(ip, "unable to allocate mac structure");
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = ip;
+ macp->m_dip = dip;
+ macp->m_src_addr = ip->curraddr;
+ macp->m_callbacks = &iprb_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = ETHERMTU;
+ macp->m_margin = VLAN_TAGSZ;
+ if (mac_register(macp, &ip->mach) != 0) {
+ iprb_error(ip, "unable to register mac with framework");
+ mac_free(macp);
+ iprb_destroy(ip);
+ return (DDI_FAILURE);
+ }
+
+ mac_free(macp);
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_detach(dev_info_t *dip)
+{
+ iprb_t *ip;
+
+ ip = ddi_get_driver_private(dip);
+ ASSERT(ip != NULL);
+
+ if (mac_disable(ip->mach) != 0)
+ return (DDI_FAILURE);
+
+ (void) mac_unregister(ip->mach);
+ iprb_destroy(ip);
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_add_intr(iprb_t *ip)
+{
+ int actual;
+
+ if (ddi_intr_alloc(ip->dip, &ip->intrh, DDI_INTR_TYPE_FIXED, 0, 1,
+ &actual, DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS) {
+ iprb_error(ip, "failed allocating interrupt handle");
+ return (DDI_FAILURE);
+ }
+
+ if (ddi_intr_add_handler(ip->intrh, iprb_intr, ip, NULL) !=
+ DDI_SUCCESS) {
+ (void) ddi_intr_free(ip->intrh);
+ ip->intrh = NULL;
+ iprb_error(ip, "failed adding interrupt handler");
+ return (DDI_FAILURE);
+ }
+ if (ddi_intr_enable(ip->intrh) != DDI_SUCCESS) {
+ (void) ddi_intr_remove_handler(ip->intrh);
+ (void) ddi_intr_free(ip->intrh);
+ ip->intrh = NULL;
+ iprb_error(ip, "failed enabling interrupt");
+ return (DDI_FAILURE);
+ }
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_dma_alloc(iprb_t *ip, iprb_dma_t *h, size_t size)
+{
+ size_t rlen;
+ ddi_dma_cookie_t dmac;
+ uint_t ndmac;
+
+ if (ddi_dma_alloc_handle(ip->dip, &dma_attr, DDI_DMA_SLEEP, NULL,
+ &h->dmah) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to allocate dma handle");
+ return (DDI_FAILURE);
+ }
+ if (ddi_dma_mem_alloc(h->dmah, size, &buf_attr, DDI_DMA_CONSISTENT,
+ DDI_DMA_SLEEP, NULL, &h->vaddr, &rlen, &h->acch) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to allocate dma memory");
+ return (DDI_FAILURE);
+ }
+ bzero(h->vaddr, size);
+ if (ddi_dma_addr_bind_handle(h->dmah, NULL, h->vaddr, size,
+ DDI_DMA_CONSISTENT | DDI_DMA_RDWR, DDI_DMA_SLEEP, NULL,
+ &dmac, &ndmac) != DDI_DMA_MAPPED) {
+ iprb_error(ip, "unable to map command memory");
+ return (DDI_FAILURE);
+ }
+ h->paddr = dmac.dmac_address;
+ return (DDI_SUCCESS);
+}
+
+void
+iprb_dma_free(iprb_dma_t *h)
+{
+ if (h->paddr != 0)
+ (void) ddi_dma_unbind_handle(h->dmah);
+ h->paddr = 0;
+ if (h->acch != NULL)
+ ddi_dma_mem_free(&h->acch);
+ h->acch = NULL;
+ if (h->dmah != NULL)
+ ddi_dma_free_handle(&h->dmah);
+ h->dmah = NULL;
+}
+
+void
+iprb_destroy(iprb_t *ip)
+{
+ int i;
+ iprb_mcast_t *mc;
+
+ /* shut down interrupts */
+ if (ip->intrh != NULL) {
+ (void) ddi_intr_disable(ip->intrh);
+ (void) ddi_intr_remove_handler(ip->intrh);
+ (void) ddi_intr_free(ip->intrh);
+ }
+ /* release DMA resources */
+ for (i = 0; i < NUM_TX; i++) {
+ iprb_dma_free(&ip->cmds[i]);
+ }
+ for (i = 0; i < NUM_RX; i++) {
+ iprb_dma_free(&ip->rxb[i]);
+ }
+ iprb_dma_free(&ip->stats);
+
+ if (ip->miih)
+ mii_free(ip->miih);
+
+ /* clean up the multicast list */
+ while ((mc = list_head(&ip->mcast)) != NULL) {
+ list_remove(&ip->mcast, mc);
+ kmem_free(mc, sizeof (*mc));
+ }
+
+ /* tear down register mappings */
+ if (ip->pcih)
+ pci_config_teardown(&ip->pcih);
+ if (ip->regsh)
+ ddi_regs_map_free(&ip->regsh);
+
+ /* clean the dip */
+ ddi_set_driver_private(ip->dip, NULL);
+
+ list_destroy(&ip->mcast);
+ mutex_destroy(&ip->culock);
+ mutex_destroy(&ip->rulock);
+
+ /* and finally toss the structure itself */
+ kmem_free(ip, sizeof (*ip));
+}
+
+void
+iprb_identify(iprb_t *ip)
+{
+ ip->devid = pci_config_get16(ip->pcih, PCI_CONF_DEVID);
+ ip->revid = pci_config_get8(ip->pcih, PCI_CONF_REVID);
+
+ switch (ip->devid) {
+ case 0x1229: /* 8255x family */
+ case 0x1030: /* Intel InBusiness */
+
+ if (ip->revid >= REV_82558_A4) {
+ ip->canpause = B_TRUE;
+ ip->canmwi = B_TRUE;
+ } else {
+ ip->is557 = B_TRUE;
+ }
+ if (ip->revid >= REV_82559_A0)
+ ip->resumebug = B_TRUE;
+ break;
+
+ case 0x1209: /* Embedded 82559ER */
+ ip->canpause = B_TRUE;
+ ip->resumebug = B_TRUE;
+ ip->canmwi = B_TRUE;
+ break;
+
+ case 0x2449: /* ICH2 */
+ case 0x1031: /* Pro/100 VE (ICH3) */
+ case 0x1032: /* Pro/100 VE (ICH3) */
+ case 0x1033: /* Pro/100 VM (ICH3) */
+ case 0x1034: /* Pro/100 VM (ICH3) */
+ case 0x1038: /* Pro/100 VM (ICH3) */
+ ip->resumebug = B_TRUE;
+ if (ip->revid >= REV_82558_A4)
+ ip->canpause = B_TRUE;
+ break;
+
+ default:
+ if (ip->revid >= REV_82558_A4)
+ ip->canpause = B_TRUE;
+ break;
+ }
+
+ /* Allow property override MWI support - not normally needed. */
+ if (ddi_prop_get_int(DDI_DEV_T_ANY, ip->dip, 0, "MWIEnable", 1) == 0) {
+ ip->canmwi = B_FALSE;
+ }
+}
+
+void
+iprb_eeprom_sendbits(iprb_t *ip, uint32_t val, uint8_t nbits)
+{
+ uint32_t mask;
+ uint16_t x;
+
+ mask = 1U << (nbits - 1);
+ while (mask) {
+ x = (mask & val) ? EEPROM_EEDI : 0;
+ PUT16(ip, CSR_EECTL, x | EEPROM_EECS);
+ drv_usecwait(100);
+ PUT16(ip, CSR_EECTL, x | EEPROM_EESK | EEPROM_EECS);
+ drv_usecwait(100);
+ PUT16(ip, CSR_EECTL, x | EEPROM_EECS);
+ drv_usecwait(100);
+ mask >>= 1;
+ }
+}
+
+uint16_t
+iprb_eeprom_read(iprb_t *ip, uint16_t address)
+{
+ uint16_t val;
+ int mask;
+ uint16_t n;
+ uint16_t bits;
+
+ /* if we don't know the address size yet call again to determine it */
+ if ((address != 0) && (ip->eeprom_bits == 0))
+ (void) iprb_eeprom_read(ip, 0);
+
+ if ((bits = ip->eeprom_bits) == 0) {
+ bits = 8;
+ ASSERT(address == 0);
+ }
+ /* enable the EEPROM chip select */
+ PUT16(ip, CSR_EECTL, EEPROM_EECS);
+ drv_usecwait(100);
+
+ /* send a read command */
+ iprb_eeprom_sendbits(ip, 6, 3);
+ n = 0;
+ for (mask = (1U << (bits - 1)); mask != 0; mask >>= 1) {
+ uint16_t x = (mask & address) ? EEPROM_EEDI : 0;
+ PUT16(ip, CSR_EECTL, x | EEPROM_EECS);
+ drv_usecwait(100);
+ PUT16(ip, CSR_EECTL, x | EEPROM_EESK | EEPROM_EECS);
+ drv_usecwait(100);
+ PUT16(ip, CSR_EECTL, x | EEPROM_EECS);
+ drv_usecwait(100);
+
+ n++;
+ /* check the dummy 0 bit */
+ if ((GET16(ip, CSR_EECTL) & EEPROM_EEDO) == 0) {
+ if (ip->eeprom_bits == 0) {
+ ip->eeprom_bits = n;
+ cmn_err(CE_CONT, "?EEPROM size %d words.\n",
+ 1U << ip->eeprom_bits);
+ }
+ break;
+ }
+ }
+ if (n != ip->eeprom_bits) {
+ iprb_error(ip, "cannot determine EEPROM size (%d, %d)",
+ ip->eeprom_bits, n);
+ }
+
+ /* shift out a 16-bit word */
+ val = 0;
+ for (mask = 0x8000; mask; mask >>= 1) {
+ PUT16(ip, CSR_EECTL, EEPROM_EECS | EEPROM_EESK);
+ drv_usecwait(100);
+ if (GET16(ip, CSR_EECTL) & EEPROM_EEDO)
+ val |= mask;
+ drv_usecwait(100);
+ PUT16(ip, CSR_EECTL, EEPROM_EECS);
+ drv_usecwait(100);
+ }
+
+ /* and disable the eeprom */
+ PUT16(ip, CSR_EECTL, 0);
+ drv_usecwait(100);
+
+ return (val);
+}
+
+int
+iprb_cmd_ready(iprb_t *ip)
+{
+ /* wait for pending SCB commands to be accepted */
+ for (int cnt = 1000000; cnt != 0; cnt -= 10) {
+ if (GET8(ip, CSR_CMD) == 0) {
+ return (DDI_SUCCESS);
+ }
+ drv_usecwait(10);
+ }
+ iprb_error(ip, "timeout waiting for chip to become ready");
+ return (DDI_FAILURE);
+}
+
+void
+iprb_cmd_reclaim(iprb_t *ip)
+{
+ while (ip->cmd_count) {
+ iprb_dma_t *cb = &ip->cmds[ip->cmd_tail];
+
+ SYNCCB(cb, CB_STS_OFFSET, 2, DDI_DMA_SYNC_FORKERNEL);
+ if ((GETCB16(cb, CB_STS_OFFSET) & CB_STS_C) == 0) {
+ break;
+ }
+
+ ip->cmd_tail++;
+ ip->cmd_tail %= NUM_TX;
+ ip->cmd_count--;
+ if (ip->cmd_count == 0) {
+ ip->tx_wdog = 0;
+ } else {
+ ip->tx_wdog = ddi_get_time();
+ }
+ }
+}
+
+int
+iprb_cmd_drain(iprb_t *ip)
+{
+ for (int i = 1000000; i; i -= 10) {
+ iprb_cmd_reclaim(ip);
+ if (ip->cmd_count == 0)
+ return (DDI_SUCCESS);
+ drv_usecwait(10);
+ }
+ iprb_error(ip, "time out waiting for commands to drain");
+ return (DDI_FAILURE);
+}
+
+int
+iprb_cmd_submit(iprb_t *ip, uint16_t cmd)
+{
+ iprb_dma_t *ncb = &ip->cmds[ip->cmd_head];
+ iprb_dma_t *lcb = &ip->cmds[ip->cmd_last];
+
+ /* If this command will consume the last CB, interrupt when done */
+ ASSERT((ip->cmd_count) < NUM_TX);
+ if (ip->cmd_count == (NUM_TX - 1)) {
+ cmd |= CB_CMD_I;
+ }
+
+ /* clear the status entry */
+ PUTCB16(ncb, CB_STS_OFFSET, 0);
+
+ /* suspend upon completion of this new command */
+ cmd |= CB_CMD_S;
+ PUTCB16(ncb, CB_CMD_OFFSET, cmd);
+ SYNCCB(ncb, 0, 0, DDI_DMA_SYNC_FORDEV);
+
+ /* clear the suspend flag from the last submitted command */
+ SYNCCB(lcb, CB_CMD_OFFSET, 2, DDI_DMA_SYNC_FORKERNEL);
+ PUTCB16(lcb, CB_CMD_OFFSET, GETCB16(lcb, CB_CMD_OFFSET) & ~CB_CMD_S);
+ SYNCCB(lcb, CB_CMD_OFFSET, 2, DDI_DMA_SYNC_FORDEV);
+
+
+ /*
+ * If the chip has a resume bug, then we need to try this as a work
+ * around. Some anecdotal evidence is that this will help solve
+ * the resume bug. Its a performance hit, but only if the EEPROM
+ * is not updated. (In theory we could do this only for 10Mbps HDX,
+ * but since it should just about never get used, we keep it simple.)
+ */
+ if (ip->resumebug) {
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ PUT8(ip, CSR_CMD, CUC_NOP);
+ (void) GET8(ip, CSR_CMD);
+ drv_usecwait(1);
+ }
+
+ /* wait for the SCB to be ready to accept a new command */
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /*
+ * Finally we can resume the CU. Note that if this the first
+ * command in the sequence (i.e. if the CU is IDLE), or if the
+ * CU is already busy working, then this CU resume command
+ * will not have any effect.
+ */
+ PUT8(ip, CSR_CMD, CUC_RESUME);
+ (void) GET8(ip, CSR_CMD); /* flush CSR */
+
+ ip->tx_wdog = ddi_get_time();
+ ip->cmd_last = ip->cmd_head;
+ ip->cmd_head++;
+ ip->cmd_head %= NUM_TX;
+ ip->cmd_count++;
+
+ return (DDI_SUCCESS);
+}
+
+iprb_dma_t *
+iprb_cmd_next(iprb_t *ip)
+{
+ if (ip->cmd_count == NUM_TX) {
+ return (NULL);
+ }
+ ASSERT(ip->cmd_count < NUM_TX);
+ return (&ip->cmds[ip->cmd_head]);
+}
+
+int
+iprb_set_unicast(iprb_t *ip)
+{
+ iprb_dma_t *cb;
+
+ ASSERT(mutex_owned(&ip->culock));
+
+ if ((cb = iprb_cmd_next(ip)) == NULL)
+ return (DDI_FAILURE);
+
+ PUTCBEA(cb, CB_IAS_ADR_OFFSET, ip->curraddr);
+ return (iprb_cmd_submit(ip, CB_CMD_IAS));
+}
+
+int
+iprb_set_multicast(iprb_t *ip)
+{
+ iprb_dma_t *cb;
+ iprb_mcast_t *mc;
+ int i;
+ list_t *l;
+
+ ASSERT(mutex_owned(&ip->culock));
+
+ if ((ip->nmcast <= 0) || (ip->nmcast > CB_MCS_CNT_MAX)) {
+ /*
+ * Only send the list if the total number of multicast
+ * address is nonzero and small enough to fit. We
+ * don't error out if it is too big, because in that
+ * case we will use the "allmulticast" support
+ * via iprb_set_config instead.
+ */
+ return (DDI_SUCCESS);
+ }
+
+ if ((cb = iprb_cmd_next(ip)) == NULL) {
+ return (DDI_FAILURE);
+ }
+
+ l = &ip->mcast;
+ for (mc = list_head(l), i = 0; mc; mc = list_next(l, mc), i++) {
+ PUTCBEA(cb, CB_MCS_ADR_OFFSET + (i * 6), mc->addr);
+ }
+ ASSERT(i == ip->nmcast);
+ PUTCB16(cb, CB_MCS_CNT_OFFSET, i);
+ return (iprb_cmd_submit(ip, CB_CMD_MCS));
+}
+
+int
+iprb_set_config(iprb_t *ip)
+{
+ iprb_dma_t *cb;
+
+ ASSERT(mutex_owned(&ip->culock));
+ if ((cb = iprb_cmd_next(ip)) == NULL) {
+ return (DDI_FAILURE);
+ }
+ PUTCB8(cb, CB_CONFIG_OFFSET + 0, 0x16);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 1, 0x8);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 2, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 3, (ip->canmwi ? 1 : 0));
+ PUTCB8(cb, CB_CONFIG_OFFSET + 4, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 5, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 6, (ip->promisc ? 0x80 : 0) | 0x3a);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 7, (ip->promisc ? 0 : 0x1) | 2);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 8, (ip->miih ? 0x1 : 0));
+ PUTCB8(cb, CB_CONFIG_OFFSET + 9, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 10, 0x2e);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 11, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 12, (ip->is557 ? 0 : 1) | 0x60);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 13, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 14, 0xf2);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 15,
+ (ip->miih ? 0x80 : 0) | (ip->promisc ? 0x1 : 0) | 0x48);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 16, 0);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 17, (ip->canpause ? 0x40 : 0));
+ PUTCB8(cb, CB_CONFIG_OFFSET + 18, (ip->is557 ? 0 : 0x8) | 0xf2);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 19,
+ ((ip->revid < REV_82558_B0) ? 0 : 0x80) |
+ (ip->canpause ? 0x18 : 0));
+ PUTCB8(cb, CB_CONFIG_OFFSET + 20, 0x3f);
+ PUTCB8(cb, CB_CONFIG_OFFSET + 21,
+ ((ip->nmcast >= CB_MCS_CNT_MAX) ? 0x8 : 0) | 0x5);
+
+ return (iprb_cmd_submit(ip, CB_CMD_CONFIG));
+}
+
+int
+iprb_set_ucode(iprb_t *ip)
+{
+ iprb_dma_t *cb;
+ const iprb_ucode_t *uc = NULL;
+ int i;
+
+ for (i = 0; iprb_ucode[i].length; i++) {
+ if (iprb_ucode[i].rev == ip->revid) {
+ uc = &iprb_ucode[i];
+ break;
+ }
+ }
+ if (uc == NULL) {
+ /* no matching firmware found, assume success */
+ return (DDI_SUCCESS);
+ }
+
+ ASSERT(mutex_owned(&ip->culock));
+ if ((cb = iprb_cmd_next(ip)) == NULL) {
+ return (DDI_FAILURE);
+ }
+ for (i = 0; i < uc->length; i++) {
+ PUTCB32(cb, (CB_UCODE_OFFSET + i * 4), uc->ucode[i]);
+ }
+ return (iprb_cmd_submit(ip, CB_CMD_UCODE));
+}
+
+int
+iprb_configure(iprb_t *ip)
+{
+ ASSERT(mutex_owned(&ip->culock));
+
+ if (iprb_cmd_drain(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ if (iprb_set_config(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ if (iprb_set_unicast(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ if (iprb_set_multicast(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ return (DDI_SUCCESS);
+}
+
+void
+iprb_stop(iprb_t *ip)
+{
+ /* go idle */
+ PUT32(ip, CSR_PORT, PORT_SEL_RESET);
+ (void) GET32(ip, CSR_PORT);
+ drv_usecwait(50);
+
+ /* shut off device interrupts */
+ PUT8(ip, CSR_INTCTL, INTCTL_MASK);
+}
+
+int
+iprb_start(iprb_t *ip)
+{
+ iprb_dma_t *cb;
+
+ ASSERT(mutex_owned(&ip->rulock));
+ ASSERT(mutex_owned(&ip->culock));
+
+ /* Reset, but first go into idle state */
+ PUT32(ip, CSR_PORT, PORT_SEL_RESET);
+ (void) GET32(ip, CSR_PORT);
+ drv_usecwait(50);
+
+ PUT32(ip, CSR_PORT, PORT_SW_RESET);
+ (void) GET32(ip, CSR_PORT);
+ drv_usecwait(10);
+ PUT8(ip, CSR_INTCTL, INTCTL_MASK);
+
+ /* Reset pointers */
+ ip->cmd_head = ip->cmd_tail = 0;
+ ip->cmd_last = NUM_TX - 1;
+
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ PUT32(ip, CSR_GEN_PTR, 0);
+ PUT8(ip, CSR_CMD, CUC_CUBASE);
+ (void) GET8(ip, CSR_CMD);
+
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ PUT32(ip, CSR_GEN_PTR, 0);
+ PUT8(ip, CSR_CMD, RUC_RUBASE);
+ (void) GET8(ip, CSR_CMD);
+
+ /* Send a NOP. This will be the first command seen by the device. */
+ cb = iprb_cmd_next(ip);
+ ASSERT(cb);
+ if (iprb_cmd_submit(ip, CB_CMD_NOP) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /* as that was the first command, go ahead and submit a CU start */
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+ PUT32(ip, CSR_GEN_PTR, cb->paddr);
+ PUT8(ip, CSR_CMD, CUC_START);
+ (void) GET8(ip, CSR_CMD);
+
+ /* Upload firmware. */
+ if (iprb_set_ucode(ip) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ /* Set up RFDs */
+ iprb_rx_init(ip);
+
+ PUT32(ip, CSR_GEN_PTR, ip->rxb[0].paddr);
+ /* wait for the SCB */
+ (void) iprb_cmd_ready(ip);
+ PUT8(ip, CSR_CMD, RUC_START);
+ (void) GET8(ip, CSR_CMD); /* flush CSR */
+
+ /* Enable device interrupts */
+ PUT8(ip, CSR_INTCTL, 0);
+ (void) GET8(ip, CSR_INTCTL);
+
+ return (DDI_SUCCESS);
+}
+
+void
+iprb_update_stats(iprb_t *ip)
+{
+ iprb_dma_t *sp = &ip->stats;
+ time_t tstamp;
+ int i;
+
+ ASSERT(mutex_owned(&ip->culock));
+
+ /* Collect the hardware stats, but don't keep redoing it */
+ if ((tstamp = ddi_get_time()) == ip->stats_time) {
+ return;
+ }
+
+ PUTSTAT(sp, STATS_DONE_OFFSET, 0);
+ SYNCSTATS(sp, 0, 0, DDI_DMA_SYNC_FORDEV);
+
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return;
+ PUT32(ip, CSR_GEN_PTR, sp->paddr);
+ PUT8(ip, CSR_CMD, CUC_STATSBASE);
+ (void) GET8(ip, CSR_CMD);
+
+ if (iprb_cmd_ready(ip) != DDI_SUCCESS)
+ return;
+ PUT8(ip, CSR_CMD, CUC_STATS_RST);
+ (void) GET8(ip, CSR_CMD); /* flush wb */
+
+ for (i = 10000; i; i -= 10) {
+ SYNCSTATS(sp, 0, 0, DDI_DMA_SYNC_FORKERNEL);
+ if (GETSTAT(sp, STATS_DONE_OFFSET) == STATS_RST_DONE) {
+ /* yay stats are updated */
+ break;
+ }
+ drv_usecwait(10);
+ }
+ if (i == 0) {
+ iprb_error(ip, "time out acquiring hardware statistics");
+ return;
+ }
+
+ ip->ex_coll += GETSTAT(sp, STATS_TX_MAXCOL_OFFSET);
+ ip->late_coll += GETSTAT(sp, STATS_TX_LATECOL_OFFSET);
+ ip->uflo += GETSTAT(sp, STATS_TX_UFLO_OFFSET);
+ ip->defer_xmt += GETSTAT(sp, STATS_TX_DEFER_OFFSET);
+ ip->one_coll += GETSTAT(sp, STATS_TX_ONECOL_OFFSET);
+ ip->multi_coll += GETSTAT(sp, STATS_TX_MULTCOL_OFFSET);
+ ip->collisions += GETSTAT(sp, STATS_TX_TOTCOL_OFFSET);
+ ip->fcs_errs += GETSTAT(sp, STATS_RX_FCS_OFFSET);
+ ip->align_errs += GETSTAT(sp, STATS_RX_ALIGN_OFFSET);
+ ip->norcvbuf += GETSTAT(sp, STATS_RX_NOBUF_OFFSET);
+ ip->oflo += GETSTAT(sp, STATS_RX_OFLO_OFFSET);
+ ip->runt += GETSTAT(sp, STATS_RX_SHORT_OFFSET);
+
+ ip->stats_time = tstamp;
+}
+
+mblk_t *
+iprb_send(iprb_t *ip, mblk_t *mp)
+{
+ iprb_dma_t *cb;
+ size_t sz;
+
+ ASSERT(mutex_owned(&ip->culock));
+
+ /* possibly reclaim some CBs */
+ iprb_cmd_reclaim(ip);
+
+ cb = iprb_cmd_next(ip);
+
+ if (cb == NULL) {
+ /* flow control */
+ ip->wantw = B_TRUE;
+ return (mp);
+ }
+
+ if ((sz = msgsize(mp)) > (ETHERMAX + VLAN_TAGSZ)) {
+ /* Generally this should never occur */
+ ip->macxmt_errs++;
+ freemsg(mp);
+ return (NULL);
+ }
+
+ ip->opackets++;
+ ip->obytes += sz;
+
+ PUTCB32(cb, CB_TX_TBD_OFFSET, 0xffffffffU);
+ PUTCB16(cb, CB_TX_COUNT_OFFSET, (sz & 0x3fff) | CB_TX_EOF);
+ PUTCB8(cb, CB_TX_THRESH_OFFSET, (sz / 8) & 0xff);
+ PUTCB8(cb, CB_TX_NUMBER_OFFSET, 0);
+ mcopymsg(mp, cb->vaddr + CB_TX_DATA_OFFSET);
+ if (cb->vaddr[CB_TX_DATA_OFFSET] & 0x1) {
+ if (bcmp(cb->vaddr + CB_TX_DATA_OFFSET, &iprb_bcast, 6) != 0) {
+ ip->multixmt++;
+ } else {
+ ip->brdcstxmt++;
+ }
+ }
+ SYNCCB(cb, 0, CB_TX_DATA_OFFSET + sz, DDI_DMA_SYNC_FORDEV);
+
+ if (iprb_cmd_submit(ip, CB_CMD_TX) != DDI_SUCCESS) {
+ ip->macxmt_errs++;
+ }
+
+ return (NULL);
+}
+
+void
+iprb_rx_add(iprb_t *ip)
+{
+ uint16_t last, curr, next;
+ iprb_dma_t *rfd, *nfd, *lfd;
+
+ ASSERT(mutex_owned(&ip->rulock));
+
+ curr = ip->rx_index;
+ last = ip->rx_last;
+ next = (curr + 1) % NUM_RX;
+
+ ip->rx_last = curr;
+ ip->rx_index = next;
+
+ lfd = &ip->rxb[last];
+ rfd = &ip->rxb[curr];
+ nfd = &ip->rxb[next];
+
+ PUTRFD32(rfd, RFD_LNK_OFFSET, nfd->paddr);
+ PUTRFD16(rfd, RFD_CTL_OFFSET, RFD_CTL_EL);
+ PUTRFD16(rfd, RFD_SIZ_OFFSET, RFD_SIZE - RFD_PKT_OFFSET);
+ PUTRFD16(rfd, RFD_CNT_OFFSET, 0);
+ SYNCRFD(rfd, 0, RFD_PKT_OFFSET, DDI_DMA_SYNC_FORDEV);
+ /* clear the suspend & EL bits from the previous RFD */
+ PUTRFD16(lfd, RFD_CTL_OFFSET, 0);
+ SYNCRFD(rfd, RFD_CTL_OFFSET, 2, DDI_DMA_SYNC_FORDEV);
+}
+
+void
+iprb_rx_init(iprb_t *ip)
+{
+ ip->rx_index = 0;
+ ip->rx_last = NUM_RX - 1;
+ for (int i = 0; i < NUM_RX; i++)
+ iprb_rx_add(ip);
+ ip->rx_index = 0;
+ ip->rx_last = NUM_RX - 1;
+}
+
+mblk_t *
+iprb_rx(iprb_t *ip)
+{
+ iprb_dma_t *rfd;
+ uint16_t cnt;
+ uint16_t sts;
+ int i;
+ mblk_t *mplist;
+ mblk_t **mpp;
+ mblk_t *mp;
+
+ mplist = NULL;
+ mpp = &mplist;
+
+ for (i = 0; i < NUM_RX; i++) {
+ rfd = &ip->rxb[ip->rx_index];
+ SYNCRFD(rfd, RFD_STS_OFFSET, 2, DDI_DMA_SYNC_FORKERNEL);
+ if ((GETRFD16(rfd, RFD_STS_OFFSET) & RFD_STS_C) == 0) {
+ break;
+ }
+
+ ip->rx_wdog = ddi_get_time();
+
+ SYNCRFD(rfd, 0, 0, DDI_DMA_SYNC_FORKERNEL);
+ cnt = GETRFD16(rfd, RFD_CNT_OFFSET);
+ cnt &= ~(RFD_CNT_EOF | RFD_CNT_F);
+ sts = GETRFD16(rfd, RFD_STS_OFFSET);
+
+ if (cnt > (ETHERMAX + VLAN_TAGSZ)) {
+ ip->toolong++;
+ iprb_rx_add(ip);
+ continue;
+ }
+ if (((sts & RFD_STS_OK) == 0) && (sts & RFD_STS_ERRS)) {
+ iprb_rx_add(ip);
+ continue;
+ }
+ if ((mp = allocb(cnt, BPRI_MED)) == NULL) {
+ ip->norcvbuf++;
+ iprb_rx_add(ip);
+ continue;
+ }
+ bcopy(rfd->vaddr + RFD_PKT_OFFSET, mp->b_wptr, cnt);
+
+ /* return it to the RFD list */
+ iprb_rx_add(ip);
+
+ mp->b_wptr += cnt;
+ ip->ipackets++;
+ ip->rbytes += cnt;
+ if (mp->b_rptr[0] & 0x1) {
+ if (bcmp(mp->b_rptr, &iprb_bcast, 6) != 0) {
+ ip->multircv++;
+ } else {
+ ip->brdcstrcv++;
+ }
+ }
+ *mpp = mp;
+ mpp = &mp->b_next;
+ }
+ return (mplist);
+}
+
+int
+iprb_m_promisc(void *arg, boolean_t on)
+{
+ iprb_t *ip = arg;
+
+ mutex_enter(&ip->culock);
+ ip->promisc = on;
+ if (ip->running && !ip->suspended)
+ (void) iprb_configure(ip);
+ mutex_exit(&ip->culock);
+ return (0);
+}
+
+int
+iprb_m_unicst(void *arg, const uint8_t *macaddr)
+{
+ iprb_t *ip = arg;
+
+ mutex_enter(&ip->culock);
+ bcopy(macaddr, ip->curraddr, 6);
+ if (ip->running && !ip->suspended)
+ (void) iprb_configure(ip);
+ mutex_exit(&ip->culock);
+ return (0);
+}
+
+int
+iprb_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
+{
+ iprb_t *ip = arg;
+ list_t *l = &ip->mcast;
+ iprb_mcast_t *mc;
+
+ if (add) {
+ mc = kmem_alloc(sizeof (*mc), KM_NOSLEEP);
+ if (mc == NULL) {
+ return (ENOMEM);
+ }
+ bcopy(macaddr, mc->addr, 6);
+ mutex_enter(&ip->culock);
+ list_insert_head(l, mc);
+ ip->nmcast++;
+ if (ip->running && !ip->suspended)
+ (void) iprb_configure(ip);
+ mutex_exit(&ip->culock);
+ } else {
+ mutex_enter(&ip->culock);
+ for (mc = list_head(l); mc != NULL; mc = list_next(l, mc)) {
+ if (bcmp(macaddr, mc->addr, 6) == 0) {
+ list_remove(&ip->mcast, mc);
+ ip->nmcast--;
+ if (ip->running && !ip->suspended)
+ (void) iprb_configure(ip);
+ break;
+ }
+ }
+ mutex_exit(&ip->culock);
+ if (mc)
+ kmem_free(mc, sizeof (*mc));
+ }
+ return (0);
+}
+
+int
+iprb_m_start(void *arg)
+{
+ int rv;
+ iprb_t *ip = arg;
+
+ mutex_enter(&ip->rulock);
+ mutex_enter(&ip->culock);
+ rv = ip->suspended ? 0 : iprb_start(ip);
+ if (rv == 0)
+ ip->running = B_TRUE;
+ ip->perh = ddi_periodic_add(iprb_periodic, ip, 5000000000, 0);
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+ if (rv == 0) {
+ if (ip->miih)
+ mii_start(ip->miih);
+ else
+ /* might be a lie. */
+ mac_link_update(ip->mach, LINK_STATE_UP);
+ }
+ return (rv ? EIO : 0);
+}
+
+void
+iprb_m_stop(void *arg)
+{
+ iprb_t *ip = arg;
+
+ if (ip->miih) {
+ mii_stop(ip->miih);
+ } else {
+ mac_link_update(ip->mach, LINK_STATE_DOWN);
+ }
+ mutex_enter(&ip->rulock);
+ mutex_enter(&ip->culock);
+ ddi_periodic_delete(ip->perh);
+
+ if (!ip->suspended) {
+ iprb_update_stats(ip);
+ iprb_stop(ip);
+ }
+ ip->running = B_FALSE;
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+}
+
+int
+iprb_m_stat(void *arg, uint_t stat, uint64_t *val)
+{
+ iprb_t *ip = arg;
+
+ if (ip->miih && (mii_m_getstat(ip->miih, stat, val) == 0)) {
+ return (0);
+ }
+
+ mutex_enter(&ip->culock);
+ if ((!ip->suspended) && (ip->running)) {
+ iprb_update_stats(ip);
+ }
+ mutex_exit(&ip->culock);
+
+ switch (stat) {
+ case MAC_STAT_IFSPEED:
+ if (ip->miih == NULL) {
+ *val = 10000000; /* 10 Mbps */
+ }
+ break;
+ case ETHER_STAT_LINK_DUPLEX:
+ if (ip->miih == NULL) {
+ *val = LINK_DUPLEX_UNKNOWN;
+ }
+ break;
+ case MAC_STAT_MULTIRCV:
+ *val = ip->multircv;
+ break;
+ case MAC_STAT_BRDCSTRCV:
+ *val = ip->brdcstrcv;
+ break;
+ case MAC_STAT_MULTIXMT:
+ *val = ip->multixmt;
+ break;
+ case MAC_STAT_BRDCSTXMT:
+ *val = ip->brdcstxmt;
+ break;
+ case MAC_STAT_IPACKETS:
+ * val = ip->ipackets;
+ break;
+ case MAC_STAT_RBYTES:
+ *val = ip->rbytes;
+ break;
+ case MAC_STAT_OPACKETS:
+ *val = ip->opackets;
+ break;
+ case MAC_STAT_OBYTES:
+ *val = ip->obytes;
+ break;
+ case MAC_STAT_NORCVBUF:
+ *val = ip->norcvbuf;
+ break;
+ case MAC_STAT_COLLISIONS:
+ *val = ip->collisions;
+ break;
+ case MAC_STAT_IERRORS:
+ *val = ip->align_errs +
+ ip->fcs_errs +
+ ip->norcvbuf +
+ ip->runt +
+ ip->toolong +
+ ip->macrcv_errs;
+ break;
+ case MAC_STAT_OERRORS:
+ *val = ip->ex_coll +
+ ip->late_coll +
+ ip->uflo +
+ ip->macxmt_errs +
+ ip->nocarrier;
+ break;
+ case ETHER_STAT_ALIGN_ERRORS:
+ *val = ip->align_errs;
+ break;
+ case ETHER_STAT_FCS_ERRORS:
+ *val = ip->fcs_errs;
+ break;
+ case ETHER_STAT_DEFER_XMTS:
+ *val = ip->defer_xmt;
+ break;
+ case ETHER_STAT_FIRST_COLLISIONS:
+ *val = ip->one_coll + ip->multi_coll + ip->ex_coll;
+ break;
+ case ETHER_STAT_MULTI_COLLISIONS:
+ *val = ip->multi_coll;
+ break;
+ case ETHER_STAT_TX_LATE_COLLISIONS:
+ *val = ip->late_coll;
+ break;
+ case ETHER_STAT_EX_COLLISIONS:
+ *val = ip->ex_coll;
+ break;
+ case MAC_STAT_OVERFLOWS:
+ *val = ip->oflo;
+ break;
+ case MAC_STAT_UNDERFLOWS:
+ *val = ip->uflo;
+ break;
+ case ETHER_STAT_TOOSHORT_ERRORS:
+ *val = ip->runt;
+ break;
+ case ETHER_STAT_TOOLONG_ERRORS:
+ *val = ip->toolong;
+ break;
+ case ETHER_STAT_CARRIER_ERRORS:
+ *val = ip->nocarrier; /* reported only for "suspend" */
+ break;
+ case ETHER_STAT_MACXMT_ERRORS:
+ *val = ip->macxmt_errs;
+ break;
+ case ETHER_STAT_MACRCV_ERRORS:
+ *val = ip->macrcv_errs;
+ break;
+ default:
+ return (ENOTSUP);
+ }
+ return (0);
+}
+
+void
+iprb_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
+ mac_prop_info_handle_t pih)
+{
+ iprb_t *ip = arg;
+
+ if (ip->miih != NULL) {
+ mii_m_propinfo(ip->miih, name, id, pih);
+ return;
+ }
+ switch (id) {
+ case MAC_PROP_DUPLEX:
+ case MAC_PROP_SPEED:
+ mac_prop_info_set_perm(pih, MAC_PROP_PERM_READ);
+ break;
+ }
+}
+
+int
+iprb_m_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t sz,
+ void *val)
+{
+ iprb_t *ip = arg;
+ uint64_t x;
+
+ if (ip->miih != NULL) {
+ return (mii_m_getprop(ip->miih, name, id, sz, val));
+ }
+ switch (id) {
+ case MAC_PROP_SPEED:
+ x = 10000000;
+ bcopy(&x, val, sizeof (x));
+ return (0);
+
+ case MAC_PROP_DUPLEX:
+ x = LINK_DUPLEX_UNKNOWN;
+ bcopy(&x, val, sizeof (x));
+ return (0);
+ }
+
+ return (ENOTSUP);
+}
+
+int
+iprb_m_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t sz,
+ const void *val)
+{
+ iprb_t *ip = arg;
+
+ if (ip->miih != NULL) {
+ return (mii_m_setprop(ip->miih, name, id, sz, val));
+ }
+ return (ENOTSUP);
+}
+
+mblk_t *
+iprb_m_tx(void *arg, mblk_t *mp)
+{
+ iprb_t *ip = arg;
+ mblk_t *nmp;
+
+ mutex_enter(&ip->culock);
+
+ while (mp != NULL) {
+ nmp = mp->b_next;
+ mp->b_next = NULL;
+ if (ip->suspended) {
+ freemsg(mp);
+ ip->nocarrier++;
+ mp = nmp;
+ continue;
+ }
+ if ((mp = iprb_send(ip, mp)) != NULL) {
+ mp->b_next = nmp;
+ break;
+ }
+ mp = nmp;
+ }
+ mutex_exit(&ip->culock);
+ return (mp);
+}
+
+void
+iprb_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
+{
+ iprb_t *ip = arg;
+
+ if ((ip->miih != NULL) && (mii_m_loop_ioctl(ip->miih, wq, mp)))
+ return;
+
+ miocnak(wq, mp, 0, EINVAL);
+}
+
+uint16_t
+iprb_mii_read(void *arg, uint8_t phy, uint8_t reg)
+{
+ iprb_t *ip = arg;
+ uint32_t mdi;
+
+ /*
+ * NB: we are guaranteed by the MII layer not to be suspended.
+ * Furthermore, we have an independent MII register.
+ */
+
+ mdi = MDI_OP_RD |
+ ((uint32_t)phy << MDI_PHYAD_SHIFT) |
+ ((uint32_t)reg << MDI_REGAD_SHIFT);
+
+ PUT32(ip, CSR_MDICTL, mdi);
+ for (int i = 0; i < 100; i++) {
+ mdi = GET32(ip, CSR_MDICTL);
+ if (mdi & MDI_R) {
+ return (mdi & 0xffff);
+ }
+ drv_usecwait(1);
+ }
+ return (0xffff);
+}
+
+void
+iprb_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
+{
+ iprb_t *ip = arg;
+ uint32_t mdi;
+
+ mdi = MDI_OP_WR |
+ ((uint32_t)phy << MDI_PHYAD_SHIFT) |
+ ((uint32_t)reg << MDI_REGAD_SHIFT) |
+ (data);
+
+ PUT32(ip, CSR_MDICTL, mdi);
+ for (int i = 0; i < 100; i++) {
+ if (GET32(ip, CSR_MDICTL) & MDI_R)
+ break;
+ }
+}
+
+void
+iprb_mii_notify(void *arg, link_state_t link)
+{
+ iprb_t *ip = arg;
+
+ mac_link_update(ip->mach, link);
+}
+
+uint_t
+iprb_intr(caddr_t arg1, caddr_t arg2)
+{
+ iprb_t *ip = (void *)arg1;
+ uint8_t sts;
+ mblk_t *mp = NULL;
+
+ _NOTE(ARGUNUSED(arg2));
+
+ mutex_enter(&ip->rulock);
+ if (ip->suspended) {
+ mutex_exit(&ip->rulock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+ sts = GET8(ip, CSR_STS);
+ if (sts == 0) {
+ /* No interrupt status! */
+ mutex_exit(&ip->rulock);
+ return (DDI_INTR_UNCLAIMED);
+ }
+ /* acknowledge the interrupts */
+ PUT8(ip, CSR_STS, sts);
+
+ if (sts & (STS_RNR | STS_FR)) {
+ mp = iprb_rx(ip);
+
+ if ((sts & STS_RNR) &&
+ ((GET8(ip, CSR_STATE) & STATE_RUS) == STATE_RUS_NORES)) {
+ iprb_rx_init(ip);
+
+ mutex_enter(&ip->culock);
+ PUT32(ip, CSR_GEN_PTR, ip->rxb[0].paddr);
+ /* wait for the SCB */
+ (void) iprb_cmd_ready(ip);
+ PUT8(ip, CSR_CMD, RUC_START);
+ (void) GET8(ip, CSR_CMD); /* flush CSR */
+ mutex_exit(&ip->culock);
+ }
+ }
+ mutex_exit(&ip->rulock);
+
+ if (mp) {
+ mac_rx(ip->mach, NULL, mp);
+ }
+ if ((sts & (STS_CNA | STS_CX)) && ip->wantw) {
+ ip->wantw = B_FALSE;
+ mac_tx_update(ip->mach);
+ }
+ return (DDI_INTR_CLAIMED);
+}
+
+void
+iprb_periodic(void *arg)
+{
+ iprb_t *ip = arg;
+ boolean_t reset = B_FALSE;
+
+ mutex_enter(&ip->rulock);
+ if (ip->suspended || !ip->running) {
+ mutex_exit(&ip->rulock);
+ return;
+ }
+
+ /*
+ * If we haven't received a packet in a while, and if the link
+ * is up, then it might be a hung chip. This problem
+ * reportedly only occurs at 10 Mbps.
+ */
+ if (ip->rxhangbug &&
+ ((ip->miih == NULL) || (mii_get_speed(ip->miih) == 10000000)) &&
+ ((ddi_get_time() - ip->rx_wdog) > ip->rx_timeout)) {
+ cmn_err(CE_CONT, "?Possible RU hang, resetting.\n");
+ reset = B_TRUE;
+ }
+
+ /* update the statistics */
+ mutex_enter(&ip->culock);
+
+ if (ip->tx_wdog && ((ddi_get_time() - ip->tx_wdog) > ip->tx_timeout)) {
+ /* transmit/CU hang? */
+ cmn_err(CE_CONT, "?CU stalled, resetting.\n");
+ reset = B_TRUE;
+ }
+
+ if (reset) {
+ /* We want to reconfigure */
+ iprb_stop(ip);
+ if (iprb_start(ip) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to restart chip");
+ }
+ }
+
+ iprb_update_stats(ip);
+
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+}
+
+int
+iprb_quiesce(dev_info_t *dip)
+{
+ iprb_t *ip = ddi_get_driver_private(dip);
+
+ /* Reset, but first go into idle state */
+ PUT32(ip, CSR_PORT, PORT_SEL_RESET);
+ drv_usecwait(50);
+ PUT32(ip, CSR_PORT, PORT_SW_RESET);
+ drv_usecwait(10);
+ PUT8(ip, CSR_INTCTL, INTCTL_MASK);
+
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_suspend(dev_info_t *dip)
+{
+ iprb_t *ip = ddi_get_driver_private(dip);
+
+ if (ip->miih)
+ mii_suspend(ip->miih);
+
+ mutex_enter(&ip->rulock);
+ mutex_enter(&ip->culock);
+ if (!ip->suspended) {
+ ip->suspended = B_TRUE;
+ if (ip->running) {
+ iprb_update_stats(ip);
+ iprb_stop(ip);
+ }
+ }
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_resume(dev_info_t *dip)
+{
+ iprb_t *ip = ddi_get_driver_private(dip);
+
+ mutex_enter(&ip->rulock);
+ mutex_enter(&ip->culock);
+
+ ip->suspended = B_FALSE;
+ if (ip->running) {
+ if (iprb_start(ip) != DDI_SUCCESS) {
+ iprb_error(ip, "unable to restart chip!");
+ ip->suspended = B_TRUE;
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+ return (DDI_FAILURE);
+ }
+ }
+
+ mutex_exit(&ip->culock);
+ mutex_exit(&ip->rulock);
+ if (ip->miih)
+ mii_resume(ip->miih);
+ return (DDI_SUCCESS);
+}
+
+int
+iprb_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ switch (cmd) {
+ case DDI_ATTACH:
+ return (iprb_attach(dip));
+
+ case DDI_RESUME:
+ return (iprb_resume(dip));
+
+ default:
+ return (DDI_FAILURE);
+ }
+}
+
+int
+iprb_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ switch (cmd) {
+ case DDI_DETACH:
+ return (iprb_detach(dip));
+
+ case DDI_SUSPEND:
+ return (iprb_suspend(dip));
+
+ default:
+ return (DDI_FAILURE);
+ }
+}
+
+void
+iprb_error(iprb_t *ip, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[256];
+
+ va_start(ap, fmt);
+ (void) vsnprintf(buf, sizeof (buf), fmt, ap);
+ va_end(ap);
+
+ cmn_err(CE_WARN, "%s%d: %s",
+ ddi_driver_name(ip->dip), ddi_get_instance(ip->dip), buf);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/iprb/iprb.h Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,373 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IPRB_H
+#define _IPRB_H
+
+/*
+ * iprb - Intel Pro/100B Ethernet Driver
+ */
+
+/*
+ * Tunables.
+ */
+#define NUM_TX 128 /* outstanding tx queue */
+#define NUM_RX 128 /* outstanding rx queue */
+
+#define RX_WATCHDOG 15 /* timeout for rx watchdog (sec) */
+#define TX_WATCHDOG 15 /* timeout for tx watchdog (sec) */
+
+/*
+ * Driver structures.
+ */
+typedef struct {
+ ddi_acc_handle_t acch;
+ ddi_dma_handle_t dmah;
+ caddr_t vaddr;
+ uint32_t paddr;
+} iprb_dma_t;
+
+typedef struct iprb_mcast {
+ list_node_t node;
+ uint8_t addr[6];
+} iprb_mcast_t;
+
+typedef struct iprb {
+ dev_info_t *dip;
+ ddi_acc_handle_t pcih;
+ ddi_acc_handle_t regsh;
+ caddr_t regs;
+
+ uint16_t devid;
+ uint8_t revid;
+
+ mac_handle_t mach;
+ mii_handle_t miih;
+
+ ddi_intr_handle_t intrh;
+
+ ddi_periodic_t perh;
+
+ kmutex_t culock;
+ kmutex_t rulock;
+
+ uint8_t factaddr[6];
+ uint8_t curraddr[6];
+
+ int nmcast;
+ list_t mcast;
+ boolean_t promisc;
+ iprb_dma_t cmds[NUM_TX];
+ iprb_dma_t rxb[NUM_RX];
+ iprb_dma_t stats;
+ time_t stats_time;
+
+ uint16_t cmd_head;
+ uint16_t cmd_last;
+ uint16_t cmd_tail;
+ uint16_t cmd_count;
+
+ uint16_t rx_index;
+ uint16_t rx_last;
+ time_t rx_wdog;
+ time_t rx_timeout;
+ time_t tx_wdog;
+ time_t tx_timeout;
+
+ uint16_t eeprom_bits;
+
+ boolean_t running;
+ boolean_t suspended;
+ boolean_t wantw;
+ boolean_t rxhangbug;
+ boolean_t resumebug;
+ boolean_t is557;
+ boolean_t canpause;
+ boolean_t canmwi;
+
+ /*
+ * Statistics
+ */
+ uint64_t ipackets;
+ uint64_t rbytes;
+ uint64_t multircv;
+ uint64_t brdcstrcv;
+ uint64_t opackets;
+ uint64_t obytes;
+ uint64_t multixmt;
+ uint64_t brdcstxmt;
+ uint64_t ex_coll;
+ uint64_t late_coll;
+ uint64_t uflo;
+ uint64_t defer_xmt;
+ uint64_t one_coll;
+ uint64_t multi_coll;
+ uint64_t collisions;
+ uint64_t fcs_errs;
+ uint64_t align_errs;
+ uint64_t norcvbuf;
+ uint64_t oflo;
+ uint64_t runt;
+ uint64_t nocarrier;
+ uint64_t toolong;
+ uint64_t macxmt_errs;
+ uint64_t macrcv_errs;
+} iprb_t;
+
+/*
+ * Idenfication values.
+ */
+#define REV_82557 1
+#define REV_82558_A4 4
+#define REV_82558_B0 5
+#define REV_82559_A0 8
+#define REV_82559S_A 9
+#define REV_82550 12
+#define REV_82550_C 13
+#define REV_82551_E 14
+#define REV_82551_F 15
+#define REV_82551_10 16
+
+/*
+ * Device registers.
+ */
+#define CSR_STATE 0x00
+#define CSR_STS 0x01
+#define CSR_CMD 0x02
+#define CSR_INTCTL 0x03
+#define CSR_GEN_PTR 0x04
+#define CSR_PORT 0x08
+#define CSR_EECTL 0x0e
+#define CSR_MDICTL 0x10
+
+#define STATE_CUS 0xc0 /* CU state (mask) */
+#define STATE_CUS_IDLE 0x00 /* CU idle */
+#define STATE_CUS_SUSP 0x40 /* CU suspended */
+#define STATE_CUS_LPQA 0x80 /* LPQ active */
+#define STATE_CUS_HQPA 0xc0 /* HQP active */
+#define STATE_RUS 0x3c /* RU state (mask) */
+#define STATE_RUS_IDLE 0x00 /* RU idle */
+#define STATE_RUS_SUSP 0x04 /* RU suspended */
+#define STATE_RUS_NORES 0x08 /* RU no resources */
+#define STATE_RUS_READY 0x10 /* RU ready */
+
+#define STS_FCP 0x01 /* flow control pause */
+#define STS_RSVD 0x02 /* reserved bit */
+#define STS_SWI 0x04 /* software interrupt */
+#define STS_MDI 0x08 /* MDI read/write done */
+#define STS_RNR 0x10 /* RU not ready */
+#define STS_CNA 0x20 /* CU state change */
+#define STS_FR 0x40 /* frame receive */
+#define STS_CX 0x80 /* cmd exec done */
+
+#define CMD_CUC 0xf0 /* CU command (mask) */
+#define CUC_NOP 0x00 /* no operation */
+#define CUC_START 0x10 /* start CU */
+#define CUC_RESUME 0x20 /* resume CU */
+#define CUC_STATSBASE 0x40 /* load statistics address */
+#define CUC_STATS 0x50 /* dump statistics */
+#define CUC_CUBASE 0x60 /* load CU base address */
+#define CUC_STATS_RST 0x70 /* dump statistics and reset */
+#define CUC_SRES 0xa0 /* static resume CU */
+#define CMD_RUC 0x07 /* RU command (mask) */
+#define RUC_NOP 0x00 /* no operation */
+#define RUC_START 0x01 /* start RU */
+#define RUC_RESUME 0x02 /* resume RU */
+#define RUC_DMAREDIR 0x03 /* receive DMA redirect */
+#define RUC_ABORT 0x40 /* abort RU */
+#define RUC_HDRSZ 0x50 /* load header data size */
+#define RUC_RUBASE 0x60 /* load RU base address */
+
+#define INTCTL_MASK 0x01 /* disable all interrupts */
+#define INTCTL_SI 0x02 /* generate software interrupt */
+#define INTCTL_FCP 0x04 /* flow control pause */
+#define INTCTL_ER 0x08 /* early receive */
+#define INTCTL_RNR 0x10 /* RU not ready */
+#define INTCTL_CNA 0x20 /* CU state change */
+#define INTCTL_FR 0x40 /* frame receive */
+#define INTCTL_CX 0x80 /* cmd exec done */
+
+#define PORT_SW_RESET 0x00
+#define PORT_SELF_TEST 0x01
+#define PORT_SEL_RESET 0x02
+
+#define EEPROM_EEDO 0x0008 /* data out */
+#define EEPROM_EEDI 0x0004 /* data in */
+#define EEPROM_EECS 0x0002 /* chip select */
+#define EEPROM_EESK 0x0001 /* clock */
+
+#define EEPROM_OP_RD 0x06
+#define EEPROM_OP_WR 0x05
+#define EEPROM_OP_WE 0x13 /* write enable */
+#define EEPROM_OP_WD 0x13 /* write disable */
+
+#define MDI_IE 0x20000000 /* interrupt enable */
+#define MDI_R 0x10000000 /* ready */
+#define MDI_OP_RD 0x08000000 /* read */
+#define MDI_OP_WR 0x04000000 /* write */
+#define MDI_PHYAD_SHIFT 21
+#define MDI_REGAD_SHIFT 16
+
+#define GET8(ip, offset) \
+ ddi_get8(ip->regsh, (void *)(ip->regs + (offset)))
+#define GET16(ip, offset) \
+ ddi_get16(ip->regsh, (void *)(ip->regs + (offset)))
+#define GET32(ip, offset) \
+ ddi_get32(ip->regsh, (void *)(ip->regs + (offset)))
+#define PUT8(ip, offset, val) \
+ ddi_put8(ip->regsh, (void *)(ip->regs + (offset)), (val))
+#define PUT16(ip, offset, val) \
+ ddi_put16(ip->regsh, (void *)(ip->regs + (offset)), (val))
+#define PUT32(ip, offset, val) \
+ ddi_put32(ip->regsh, (void *)(ip->regs + (offset)), (val))
+
+
+#define PUTDMA8(d, off, val) \
+ ddi_put8(d->acch, (void *)(d->vaddr + (off)), LE_8(val))
+#define PUTDMA16(d, off, val) \
+ ddi_put16(d->acch, (void *)(d->vaddr + (off)), LE_16(val))
+#define PUTDMA32(d, off, val) \
+ ddi_put32(d->acch, (void *)(d->vaddr + (off)), LE_32(val))
+#define GETDMA8(d, off) \
+ LE_8(ddi_get8(d->acch, (void *)(d->vaddr + (off))))
+#define GETDMA16(d, off) \
+ LE_16(ddi_get16(d->acch, (void *)(d->vaddr + (off))))
+#define GETDMA32(d, off) \
+ LE_32(ddi_get32(d->acch, (void *)(d->vaddr + (off))))
+#define SYNCDMA(d, off, size, dir) \
+ (void) ddi_dma_sync(d->dmah, off, size, dir)
+
+/*
+ * Command block offsets.
+ */
+#define CB_STS_OFFSET 0
+#define CB_CMD_OFFSET 2
+#define CB_LNK_OFFSET 4
+#define CB_SIZE 2048 /* size of cmd blk */
+
+#define CB_IAS_ADR_OFFSET 8
+
+#define CB_MCS_CNT_OFFSET 8
+#define CB_MCS_ADR_OFFSET 10
+#define CB_MCS_CNT_MAX ((CB_SIZE - CB_MCS_ADR_OFFSET) / 6)
+
+#define CB_UCODE_OFFSET 8
+
+#define CB_CONFIG_OFFSET 8
+
+#define CB_TX_TBD_OFFSET 8
+#define CB_TX_COUNT_OFFSET 12
+#define CB_TX_EOF 0x8000
+#define CB_TX_THRESH_OFFSET 14
+#define CB_TX_NUMBER_OFFSET 15
+#define CB_TX_DATA_OFFSET 16
+
+#define PUTCB8(cb, o, v) PUTDMA8(cb, o, v)
+#define PUTCB16(cb, o, v) PUTDMA16(cb, o, v)
+#define PUTCB32(cb, o, v) PUTDMA32(cb, o, v)
+#define PUTCBEA(cb, o, enet) \
+ ddi_rep_put8(cb->acch, enet, (void *)(cb->vaddr + (o)), 6, \
+ DDI_DEV_AUTOINCR);
+#define GETCB8(cb, o) GETDMA8(cb, o)
+#define GETCB16(cb, o) GETDMA16(cb, o)
+#define GETCB32(cb, o) GETDMA32(cb, o)
+#define SYNCCB(cb, o, s, dir) SYNCDMA(cb, o, s, dir)
+/*
+ * CB status bits.
+ */
+#define CB_STS_OK 0x2000
+#define CB_STS_C 0x8000
+
+/*
+ * Commands.
+ */
+#define CB_CMD_NOP 0x0
+#define CB_CMD_IAS 0x1
+#define CB_CMD_CONFIG 0x2
+#define CB_CMD_MCS 0x3
+#define CB_CMD_TX 0x4
+#define CB_CMD_UCODE 0x5
+/* and flags to go with */
+#define CB_CMD_SF 0x0008 /* simple/flex */
+#define CB_CMD_I 0x2000 /* generate an interrupt */
+#define CB_CMD_S 0x4000 /* suspend on completion */
+#define CB_CMD_EL 0x8000 /* end of list */
+
+/*
+ * RFD offsets.
+ */
+#define GETRFD16(r, o) GETDMA16(r, o)
+#define PUTRFD16(r, o, v) PUTDMA16(r, o, v)
+#define PUTRFD32(r, o, v) PUTDMA32(r, o, v)
+#define SYNCRFD(r, o, s, dir) SYNCDMA(r, o, s, dir)
+
+#define RFD_STS_OFFSET 0x00
+#define RFD_CTL_OFFSET 0x02
+#define RFD_LNK_OFFSET 0x04
+#define RFD_CNT_OFFSET 0x0c /* bytes received */
+#define RFD_SIZ_OFFSET 0x0e /* size of packet area */
+#define RFD_PKT_OFFSET 0x10
+#define RFD_SIZE 2048
+
+#define RFD_CTL_EL 0x8000
+#define RFD_CTL_S 0x4000
+#define RFD_CTL_H 0x0010
+#define RFD_CTL_SF 0x0008
+
+#define RFD_STS_C 0x8000
+#define RFD_STS_OK 0x2000
+#define RFD_STS_FCS 0x0800
+#define RFD_STS_ALIGN 0x0400
+#define RFD_STS_TOOBIG 0x0200
+#define RFD_STS_DMAOFLO 0x0100
+#define RFD_STS_TOOSHORT 0x0080
+#define RFD_STS_802 0x0020
+#define RFD_STS_RXERR 0x0010
+#define RFD_STS_NOMATCH 0x0004
+#define RFD_STS_IAMATCH 0x0002
+#define RFD_STS_COLL_TCO 0x0001
+#define RFD_STS_ERRS 0x0d90
+
+#define RFD_CNT_EOF 0x8000
+#define RFD_CNT_F 0x4000
+
+/*
+ * Stats offsets.
+ */
+#define STATS_TX_GOOD_OFFSET 0
+#define STATS_TX_MAXCOL_OFFSET 4
+#define STATS_TX_LATECOL_OFFSET 8
+#define STATS_TX_UFLO_OFFSET 16
+#define STATS_TX_DEFER_OFFSET 20
+#define STATS_TX_ONECOL_OFFSET 24
+#define STATS_TX_MULTCOL_OFFSET 28
+#define STATS_TX_TOTCOL_OFFSET 32
+#define STATS_RX_GOOD_OFFSET 36
+#define STATS_RX_FCS_OFFSET 40
+#define STATS_RX_ALIGN_OFFSET 44
+#define STATS_RX_NOBUF_OFFSET 48
+#define STATS_RX_OFLO_OFFSET 52
+#define STATS_RX_COL_OFFSET 56
+#define STATS_RX_SHORT_OFFSET 60
+#define STATS_DONE_OFFSET 64
+#define STATS_SIZE 68
+#define STATS_DONE 0xa005
+#define STATS_RST_DONE 0xa007
+
+#define SYNCSTATS(sp, o, s, dir) SYNCDMA(sp, o, s, dir)
+#define PUTSTAT(sp, o, v) PUTDMA32(sp, o, v)
+#define GETSTAT(sp, o) GETDMA32(sp, o)
+
+#endif /* _IPRB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/iprb/rcvbundl.h Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,1090 @@
+/*
+Copyright (c) 1999-2001, Intel Corporation
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * rcvbundl.h
+ *
+ * Author: Patrick J Luhmann (PJL)
+ * Date: 05/30/2000
+ * Version: 3.28
+ *
+ * This file contains the loadable micro code arrays to implement
+ * receive bundling on the D101 A-step, D101 B-step, D101M (B-step
+ * only), D101S, D102 B-step, D102 C-step and D102 E-step.
+ *
+ * Each controller has its own specific micro code array. The array
+ * for one controller is totally incompatible with any other
+ * controller, and if used will most likely cause the controller to
+ * lock up and stop responding to the driver. Each micro code array
+ * has its own parameter offsets (described below), and they each have
+ * their own version number (which should not be confused with the
+ * version of the rcvbundl.h file given above).
+ */
+
+/* Note: Minor formatting changes made for illumos. */
+
+/*
+ * CPUSaver parameters
+ *
+ * All CPUSaver parameters are 16-bit literals that are part of a
+ * "move immediate value" instruction. By changing the value of the
+ * literal in the instruction before the code is loaded, the driver
+ * can change algorithm.
+ *
+ * CPUSAVER_DWORD - This is the location of the instruction that loads
+ * the dead-man timer with its inital value. By writing a 16-bit
+ * value to the low word of this instruction, the driver can change
+ * the timer value. The current default is either x600 or x800;
+ * experiments show that the value probably should stay within the
+ * range of x200 - x1000.
+ *
+ * CPUSAVER_BUNDLE_MAX_DWORD - This is the location of the instruction
+ * that sets the maximum number of frames that will be bundled. In
+ * some situations, such as the TCP windowing algorithm, it may be
+ * better to limit the growth of the bundle size than let it go as
+ * high as it can, because that could cause too much added latency.
+ * The default is six, because this is the number of packets in the
+ * default TCP window size. A value of 1 would make CPUSaver
+ * indicate an interrupt for every frame received. If you do not
+ * want to put a limit on the bundle size, set this value to xFFFF.
+ *
+ * CPUSAVER_MIN_SIZE_DWORD - This is the location of the instruction
+ * that contains a bit-mask describing the minimum size frame that
+ * will be bundled. The default masks the lower 7 bits, which
+ * means that any frame less than 128 bytes in length will not be
+ * bundled, but will instead immediately generate an interrupt.
+ * This does not affect the current bundle in any way. Any frame
+ * that is 128 bytes or large will be bundled normally. This
+ * feature is meant to provide immediate indication of ACK frames
+ * in a TCP environment. Customers were seeing poor performance
+ * when a machine with CPUSaver enabled was sending but not
+ * receiving. The delay introduced when the ACKs were received was
+ * enough to reduce total throughput, because the sender would sit
+ * idle until the ACK was finally seen.
+ *
+ * The current default is 0xFF80, which masks out the lower 7 bits.
+ * This means that any frame which is x7F (127) bytes or smaller
+ * will cause an immediate interrupt. Because this value must be a
+ * bit mask, there are only a few valid values that can be used.
+ * To turn this feature off, the driver can write the value xFFFF
+ * to the lower word of this instruction (in the same way that the
+ * other parameters are used). Likewise, a value of 0xF800 (2047)
+ * would cause an interrupt to be generated for every frame,
+ * because all standard Ethernet frames are <= 2047 bytes in
+ * length.
+ */
+
+
+
+/*
+ * CPUSaver micro code for the D101A
+ */
+
+/* Version 2.0 */
+
+/* This value is the same for both A and B step of 558. */
+#define D101_CPUSAVER_DWORD 72
+
+#define D101_A_RCVBUNDLE_UCODE \
+{\
+0x03B301BB, \
+0x0046FFFF, \
+0xFFFFFFFF, \
+0x051DFFFF, \
+0xFFFFFFFF, \
+0xFFFFFFFF, \
+0x000C0001, \
+0x00101212, \
+0x000C0008, \
+0x003801BC, \
+0x00000000, \
+0x00124818, \
+0x000C1000, \
+0x00220809, \
+0x00010200, \
+0x00124818, \
+0x000CFFFC, \
+0x003803B5, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x0024B81D, \
+0x00130836, \
+0x000C0001, \
+0x0026081C, \
+0x0020C81B, \
+0x00130824, \
+0x00222819, \
+0x00101213, \
+0x00041000, \
+0x003A03B3, \
+0x00010200, \
+0x00101B13, \
+0x00238081, \
+0x00213049, \
+0x0038003B, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x0024B83E, \
+0x00130826, \
+0x000C0001, \
+0x0026083B, \
+0x00010200, \
+0x00134824, \
+0x000C0001, \
+0x00101213, \
+0x00041000, \
+0x0038051E, \
+0x00101313, \
+0x00010400, \
+0x00380521, \
+0x00050600, \
+0x00100824, \
+0x00101310, \
+0x00041000, \
+0x00080600, \
+0x00101B10, \
+0x0038051E, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+}
+
+
+/*
+ * CPUSaver micro code for the D101B
+ */
+
+/* Version 2.0 */
+#define D101_B0_CPUSAVER_DWORD 72
+
+#define D101_B0_RCVBUNDLE_UCODE \
+{\
+0x03B401BC, \
+0x0047FFFF, \
+0xFFFFFFFF, \
+0x051EFFFF, \
+0xFFFFFFFF, \
+0xFFFFFFFF, \
+0x000C0001, \
+0x00101B92, \
+0x000C0008, \
+0x003801BD, \
+0x00000000, \
+0x00124818, \
+0x000C1000, \
+0x00220809, \
+0x00010200, \
+0x00124818, \
+0x000CFFFC, \
+0x003803B6, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x0024B81D, \
+0x0013082F, \
+0x000C0001, \
+0x0026081C, \
+0x0020C81B, \
+0x00130837, \
+0x00222819, \
+0x00101B93, \
+0x00041000, \
+0x003A03B4, \
+0x00010200, \
+0x00101793, \
+0x00238082, \
+0x0021304A, \
+0x0038003C, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x0024B83E, \
+0x00130826, \
+0x000C0001, \
+0x0026083B, \
+0x00010200, \
+0x00134837, \
+0x000C0001, \
+0x00101B93, \
+0x00041000, \
+0x0038051F, \
+0x00101313, \
+0x00010400, \
+0x00380522, \
+0x00050600, \
+0x00100837, \
+0x00101310, \
+0x00041000, \
+0x00080600, \
+0x00101790, \
+0x0038051F, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+}
+
+
+/*
+ * CPUSaver micro code for the D101M (B-step only)
+ */
+
+/* Version 2.10 */
+
+/* Parameter values for the D101M B-step */
+#define D101M_CPUSAVER_DWORD 78
+#define D101M_CPUSAVER_BUNDLE_MAX_DWORD 65
+#define D101M_CPUSAVER_MIN_SIZE_DWORD 126
+
+#define D101M_B_RCVBUNDLE_UCODE \
+{\
+0x00550215, \
+0xFFFF0437, \
+0xFFFFFFFF, \
+0x06A70789, \
+0xFFFFFFFF, \
+0x0558FFFF, \
+0x000C0001, \
+0x00101312, \
+0x000C0008, \
+0x00380216, \
+0x0010009C, \
+0x00204056, \
+0x002380CC, \
+0x00380056, \
+0x0010009C, \
+0x00244C0B, \
+0x00000800, \
+0x00124818, \
+0x00380438, \
+0x00000000, \
+0x00140000, \
+0x00380555, \
+0x00308000, \
+0x00100662, \
+0x00100561, \
+0x000E0408, \
+0x00134861, \
+0x000C0002, \
+0x00103093, \
+0x00308000, \
+0x00100624, \
+0x00100561, \
+0x000E0408, \
+0x00100861, \
+0x000C007E, \
+0x00222C21, \
+0x000C0002, \
+0x00103093, \
+0x00380C7A, \
+0x00080000, \
+0x00103090, \
+0x00380C7A, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x00244C2D, \
+0x00010004, \
+0x00041000, \
+0x003A0437, \
+0x00044010, \
+0x0038078A, \
+0x00000000, \
+0x00100099, \
+0x00206C7A, \
+0x0010009C, \
+0x00244C48, \
+0x00130824, \
+0x000C0001, \
+0x00101213, \
+0x00260C75, \
+0x00041000, \
+0x00010004, \
+0x00130826, \
+0x000C0006, \
+0x002206A8, \
+0x0013C926, \
+0x00101313, \
+0x003806A8, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00080600, \
+0x00101B10, \
+0x00050004, \
+0x00100826, \
+0x00101210, \
+0x00380C34, \
+0x00000000, \
+0x00000000, \
+0x0021155B, \
+0x00100099, \
+0x00206559, \
+0x0010009C, \
+0x00244559, \
+0x00130836, \
+0x000C0000, \
+0x00220C62, \
+0x000C0001, \
+0x00101B13, \
+0x00229C0E, \
+0x00210C0E, \
+0x00226C0E, \
+0x00216C0E, \
+0x0022FC0E, \
+0x00215C0E, \
+0x00214C0E, \
+0x00380555, \
+0x00010004, \
+0x00041000, \
+0x00278C67, \
+0x00040800, \
+0x00018100, \
+0x003A0437, \
+0x00130826, \
+0x000C0001, \
+0x00220559, \
+0x00101313, \
+0x00380559, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00130831, \
+0x0010090B, \
+0x00124813, \
+0x000CFF80, \
+0x002606AB, \
+0x00041000, \
+0x003806A8, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+}
+
+
+/*
+ * CPUSaver micro code for the D101S
+ */
+
+/* Version 1.20 */
+
+/* Parameter values for the D101S */
+#define D101S_CPUSAVER_DWORD 78
+#define D101S_CPUSAVER_BUNDLE_MAX_DWORD 67
+#define D101S_CPUSAVER_MIN_SIZE_DWORD 129
+
+
+#define D101S_RCVBUNDLE_UCODE \
+{\
+0x00550242, \
+0xFFFF047E, \
+0xFFFFFFFF, \
+0x06FF0818, \
+0xFFFFFFFF, \
+0x05A6FFFF, \
+0x000C0001, \
+0x00101312, \
+0x000C0008, \
+0x00380243, \
+0x0010009C, \
+0x00204056, \
+0x002380D0, \
+0x00380056, \
+0x0010009C, \
+0x00244F8B, \
+0x00000800, \
+0x00124818, \
+0x0038047F, \
+0x00000000, \
+0x00140000, \
+0x003805A3, \
+0x00308000, \
+0x00100610, \
+0x00100561, \
+0x000E0408, \
+0x00134861, \
+0x000C0002, \
+0x00103093, \
+0x00308000, \
+0x00100624, \
+0x00100561, \
+0x000E0408, \
+0x00100861, \
+0x000C007E, \
+0x00222FA1, \
+0x000C0002, \
+0x00103093, \
+0x00380F90, \
+0x00080000, \
+0x00103090, \
+0x00380F90, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x0010009C, \
+0x00244FAD, \
+0x00010004, \
+0x00041000, \
+0x003A047E, \
+0x00044010, \
+0x00380819, \
+0x00000000, \
+0x00100099, \
+0x00206FFD, \
+0x0010009A, \
+0x0020AFFD, \
+0x0010009C, \
+0x00244FC8, \
+0x00130824, \
+0x000C0001, \
+0x00101213, \
+0x00260FF8, \
+0x00041000, \
+0x00010004, \
+0x00130826, \
+0x000C0006, \
+0x00220700, \
+0x0013C926, \
+0x00101313, \
+0x00380700, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00080600, \
+0x00101B10, \
+0x00050004, \
+0x00100826, \
+0x00101210, \
+0x00380FB6, \
+0x00000000, \
+0x00000000, \
+0x002115A9, \
+0x00100099, \
+0x002065A7, \
+0x0010009A, \
+0x0020A5A7, \
+0x0010009C, \
+0x002445A7, \
+0x00130836, \
+0x000C0000, \
+0x00220FE4, \
+0x000C0001, \
+0x00101B13, \
+0x00229F8E, \
+0x00210F8E, \
+0x00226F8E, \
+0x00216F8E, \
+0x0022FF8E, \
+0x00215F8E, \
+0x00214F8E, \
+0x003805A3, \
+0x00010004, \
+0x00041000, \
+0x00278FE9, \
+0x00040800, \
+0x00018100, \
+0x003A047E, \
+0x00130826, \
+0x000C0001, \
+0x002205A7, \
+0x00101313, \
+0x003805A7, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00130831, \
+0x0010090B, \
+0x00124813, \
+0x000CFF80, \
+0x00260703, \
+0x00041000, \
+0x00380700, \
+0x00000000, \
+}
+
+
+/*
+ * CPUSaver micro code for the D102 B-step
+ */
+
+/* Version 2.0 */
+
+/*
+ * This version of CPUSaver is different from all others in a
+ * different way. It combines the CPUSaver algorithm with fixes for
+ * bugs in the B-step hardware (specifically, bugs with Inline
+ * Receive). Thus, when CPUSaver is disabled, this micro code image
+ * will still need to be loaded. Before this happens, the hit
+ * addresses for the CPUSaver algorithm must be set to 0x1FFFF. The
+ * hit addresses for CPUSaver are (starting with 0, and remember that.
+ */
+
+/* Parameter values for the D102 B-step */
+#define D102_B_CPUSAVER_DWORD 91
+#define D102_B_CPUSAVER_BUNDLE_MAX_DWORD 115
+#define D102_B_CPUSAVER_MIN_SIZE_DWORD 70
+
+#define D102_B_RCVBUNDLE_UCODE \
+{\
+0x006F0276, \
+0x02BF0E93, \
+0x1FFF0ED9, \
+0x0D2508FA, \
+0x04D21FFF, \
+0x0EA10892, \
+0x00300001, \
+0x0140D871, \
+0x00300008, \
+0x00E00277, \
+0x01406C57, \
+0x00816073, \
+0x008700FA, \
+0x00E00070, \
+0x00E00E94, \
+0x00200004, \
+0x01410000, \
+0x014B6F6F, \
+0x0030FFFF, \
+0x01486F72, \
+0x00E81F9B, \
+0x00E00EA3, \
+0x003C0040, \
+0x00380920, \
+0x00C02000, \
+0x0150ED38, \
+0x0150EE39, \
+0x0150EF3A, \
+0x003C0040, \
+0x01506F0D, \
+0x01600E72, \
+0x00380AE0, \
+0x00E002C0, \
+0x00300001, \
+0x014C0000, \
+0x008404DC, \
+0x014C6F72, \
+0x00E01F9D, \
+0x01406C51, \
+0x0080DFC2, \
+0x01406C52, \
+0x00815FC2, \
+0x01406C57, \
+0x00917FD5, \
+0x00E01FE6, \
+0x00000000, \
+0x01406C57, \
+0x00919FAD, \
+0x00038800, \
+0x00300000, \
+0x00E81FF2, \
+0x014D6FC4, \
+0x00E008FB, \
+0x00000000, \
+0x00822D30, \
+0x01406C51, \
+0x0080CD26, \
+0x01406C52, \
+0x00814D26, \
+0x01406C57, \
+0x00916D26, \
+0x014C6FD7, \
+0x00300000, \
+0x00841FDB, \
+0x00300001, \
+0x0140D772, \
+0x00E012B3, \
+0x014C6F91, \
+0x0150710B, \
+0x01496F72, \
+0x0030FF80, \
+0x00940EDD, \
+0x00102000, \
+0x00E00EDA, \
+0x01406C57, \
+0x00917FFD, \
+0x00001000, \
+0x00E01FFD, \
+0x00138800, \
+0x00300001, \
+0x00E81FF2, \
+0x00202500, \
+0x00E81F9B, \
+0x01600EC5, \
+0x00E00893, \
+0x00000000, \
+0x01406CD5, \
+0x0091EEA3, \
+0x00904EA3, \
+0x00901F89, \
+0x00E00EA3, \
+0x00200600, \
+0x0140D76F, \
+0x00138400, \
+0x01406FD8, \
+0x0140D96F, \
+0x00E01FE6, \
+0x00038400, \
+0x00102000, \
+0x00971FE0, \
+0x00101000, \
+0x00050200, \
+0x00E804D2, \
+0x014C6FD8, \
+0x00300001, \
+0x00840D26, \
+0x0140D872, \
+0x00E00D26, \
+0x014C6FD9, \
+0x00300001, \
+0x0140D972, \
+0x00941FBD, \
+0x00102000, \
+0x00038400, \
+0x014C6FD8, \
+0x00300006, \
+0x00840EDA, \
+0x014F71D8, \
+0x0140D872, \
+0x00E00EDA, \
+0x00340020, \
+0x014C6FED, \
+0x01603472, \
+0x016035EE, \
+0x016036EF, \
+0x00300004, \
+0x01611C71, \
+0x00300014, \
+0x00200A00, \
+0x00E810B9, \
+0x00600000, \
+0x01496F50, \
+0x00E004D3, \
+0x00000000, \
+}
+
+
+/*
+ * Micro code for the D102 C-step
+ */
+
+/* Parameter values for the D102 C-step */
+#define D102_C_CPUSAVER_DWORD 46
+#define D102_C_CPUSAVER_BUNDLE_MAX_DWORD 54
+#define D102_C_CPUSAVER_MIN_SIZE_DWORD 133 /* not implemented */
+
+#define D102_C_RCVBUNDLE_UCODE \
+{ \
+0x00700279, \
+0x0E6104E2, \
+0x02BF0CAE, \
+0x1519150C, \
+0x1FFF0E5B, \
+0x1FFF1FFF, \
+0x00E014D8, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014DC, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014F4, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014E0, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014E7, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00141000, \
+0x015D6F0D, \
+0x00E002C0, \
+0x00000000, \
+0x00200600, \
+0x00E0150D, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00300006, \
+0x00E0151A, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00906E65, \
+0x00800E60, \
+0x00E00E5D, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+}
+
+/*
+ * Micro code for the D102 E-step
+ */
+
+/* Parameter values for the D102 E-step */
+#define D102_E_CPUSAVER_DWORD 42
+#define D102_E_CPUSAVER_BUNDLE_MAX_DWORD 54
+#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46
+
+#define D102_E_RCVBUNDLE_UCODE \
+{\
+0x007D028F, \
+0x0E4204F9, \
+0x14ED0C85, \
+0x14FA14E9, \
+0x0EF70E36, \
+0x1FFF1FFF, \
+0x00E014B9, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014BD, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014D5, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014C1, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00E014C8, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00200600, \
+0x00E014EE, \
+0x00000000, \
+0x00000000, \
+0x0030FF80, \
+0x00940E46, \
+0x00038200, \
+0x00102000, \
+0x00E00E43, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00300006, \
+0x00E014FB, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00906E41, \
+0x00800E3C, \
+0x00E00E39, \
+0x00000000, \
+0x00906EFD, \
+0x00900EFD, \
+0x00E00EF8, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+0x00000000, \
+}
--- a/usr/src/uts/intel/Makefile.intel.shared Thu Dec 02 20:23:12 2010 +0530
+++ b/usr/src/uts/intel/Makefile.intel.shared Fri Dec 03 07:32:02 2010 -0800
@@ -369,7 +369,6 @@
$(CLOSED_BUILD)CLOSED_DRV_KMODS += bmc
$(CLOSED_BUILD)CLOSED_DRV_KMODS += glm
$(CLOSED_BUILD)CLOSED_DRV_KMODS += intel_nhmex
-$(CLOSED_BUILD)CLOSED_DRV_KMODS += iprb
$(CLOSED_BUILD)CLOSED_DRV_KMODS += cpqary3
$(CLOSED_BUILD)CLOSED_DRV_KMODS += marvell88sx
$(CLOSED_BUILD)CLOSED_DRV_KMODS += bcm_sata
@@ -398,6 +397,7 @@
DRV_KMODS += sfe
DRV_KMODS += amd8111s
DRV_KMODS += igb
+DRV_KMODS += iprb
DRV_KMODS += ixgbe
DRV_KMODS += vr
$(CLOSED_BUILD)CLOSED_DRV_KMODS += ixgb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/iprb/Makefile Fri Dec 03 07:32:02 2010 -0800
@@ -0,0 +1,86 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = iprb
+OBJECTS = $(IPRB_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(IPRB_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Overrides
+#
+
+#
+# Driver depends on GLD
+#
+LDFLAGS += -dy -N misc/mac -Nmisc/mii
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ