summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlucy wang - Sun Microsystems - Beijing China <xiuyan.wang@Sun.COM>2008-10-28 10:06:13 +0800
committerlucy wang - Sun Microsystems - Beijing China <xiuyan.wang@Sun.COM>2008-10-28 10:06:13 +0800
commit9a5557fdd04be37785607871e8d4189e39490129 (patch)
treee9aa795e4713a1bf41abda1ed78591d7cfdd87a3
parent8bef02c349382d38de7fe253bf68f1404bf02374 (diff)
downloadillumos-joyent-9a5557fdd04be37785607871e8d4189e39490129.tar.gz
PSARC 2008/045 NetXen 10 Gigabit Ethernet Driver
6472698 NetXen 1Gb/10Gb nic driver
-rw-r--r--usr/src/pkgdefs/Makefile3
-rw-r--r--usr/src/pkgdefs/SUNWntxn/Makefile37
-rw-r--r--usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl45
-rw-r--r--usr/src/pkgdefs/SUNWntxn/postinstall138
-rw-r--r--usr/src/pkgdefs/SUNWntxn/postremove37
-rw-r--r--usr/src/pkgdefs/SUNWntxn/prototype_com50
-rw-r--r--usr/src/pkgdefs/SUNWntxn/prototype_i38648
-rw-r--r--usr/src/tools/opensolaris/license-list1
-rw-r--r--usr/src/uts/common/Makefile.files6
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE4
-rw-r--r--usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/uts/common/io/ntxn/driver_info.h67
-rw-r--r--usr/src/uts/common/io/ntxn/message.h31
-rw-r--r--usr/src/uts/common/io/ntxn/nic_cmn.h729
-rw-r--r--usr/src/uts/common/io/ntxn/nic_phan_reg.h161
-rw-r--r--usr/src/uts/common/io/ntxn/niu.c689
-rw-r--r--usr/src/uts/common/io/ntxn/nx_errorcode.h81
-rw-r--r--usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h168
-rw-r--r--usr/src/uts/common/io/ntxn/nxhal_nic_interface.h545
-rw-r--r--usr/src/uts/common/io/ntxn/unm_brdcfg.h273
-rw-r--r--usr/src/uts/common/io/ntxn/unm_gem.c1489
-rw-r--r--usr/src/uts/common/io/ntxn/unm_inc.h1777
-rw-r--r--usr/src/uts/common/io/ntxn/unm_ndd.c499
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic.h819
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_ctx.c655
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_hw.c2204
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_hw.h107
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_init.c512
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_ioctl.h79
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_isr.c127
-rw-r--r--usr/src/uts/common/io/ntxn/unm_nic_main.c2599
-rw-r--r--usr/src/uts/common/io/ntxn/unm_version.h31
-rw-r--r--usr/src/uts/intel/Makefile.intel.shared1
-rw-r--r--usr/src/uts/intel/ntxn/Makefile95
35 files changed, 14114 insertions, 1 deletions
diff --git a/usr/src/pkgdefs/Makefile b/usr/src/pkgdefs/Makefile
index 5a53056b4b..d12b18d8b8 100644
--- a/usr/src/pkgdefs/Makefile
+++ b/usr/src/pkgdefs/Makefile
@@ -157,7 +157,8 @@ i386_SUBDIRS= \
SUNWxsvc \
SUNWxvmipar \
SUNWxvmipau \
- SUNWxvmpv
+ SUNWxvmpv \
+ SUNWntxn
i386_XMODS= \
BRCMbnx \
diff --git a/usr/src/pkgdefs/SUNWntxn/Makefile b/usr/src/pkgdefs/SUNWntxn/Makefile
new file mode 100644
index 0000000000..3352084f9e
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/Makefile
@@ -0,0 +1,37 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+LICENSEFILES += ../../uts/common/io/ntxn/THIRDPARTYLICENSE
+
+.KEEP_STATE:
+
+all: $(FILES) postinstall postremove
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl b/usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl
new file mode 100644
index 0000000000..9538fdd5fa
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl
@@ -0,0 +1,45 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PKG=SUNWntxn
+NAME=NetXen 1Gb/10Gb NIC Driver
+ARCH="ISA"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGVERS="1.0"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+CATEGORY=system
+VENDOR="Sun Microsystems, Inc."
+DESC="NetXen 1Gb/10Gb Ethernet Adapter Driver"
+CLASSES="none preserve"
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+BASEDIR=/
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
diff --git a/usr/src/pkgdefs/SUNWntxn/postinstall b/usr/src/pkgdefs/SUNWntxn/postinstall
new file mode 100644
index 0000000000..af5b4655fe
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/postinstall
@@ -0,0 +1,138 @@
+#!/sbin/sh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# Function: check_add_drv()
+#
+# This function will check if the module has an entry in etc/name_to_major
+# If not simply calls add_drv with the arguments given. If there is
+# such an entry in name_to_major file, it adds entries in driver_aliases
+# driver_classes and minor_perm if necessary.
+# The syntax of this function is the same as add_drv.
+
+check_add_drv()
+{
+ if [ "$BASEDIR" = "" ]
+ then
+ BASEDIR=/
+ fi
+ alias=""
+ class=""
+ ADD_ALIAS=0
+ ADD_CLASS=0
+ ADD_MINOR=0
+ OPTIND=1
+ IS_NET_DRIVER=0
+
+ cmd="add_drv"
+
+ NO_CMD=
+ while getopts i:b:m:c:N opt
+ do
+ case $opt in
+ N ) NO_CMD=1;;
+ i ) ADD_ALIAS=1
+ alias=$OPTARG
+ cmd=$cmd" -i '$alias'"
+ ;;
+ m ) ADD_MINOR=1
+ minor=$OPTARG
+ cmd=$cmd" -m '$minor'"
+ ;;
+ c) ADD_CLASS=1
+ class=$OPTARG
+ cmd=$cmd" -c $class"
+ ;;
+ b) BASEDIR=$OPTARG
+ cmd=$cmd" -b $BASEDIR"
+ ;;
+ \?) echo "check_add_drv can not handle this option"
+ return
+ ;;
+ esac
+ done
+ shift `/usr/bin/expr $OPTIND - 1`
+
+ drvname=$1
+
+ cmd=$cmd" "$drvname
+
+ drvname=`echo $drvname | /usr/bin/sed 's;.*/;;g'`
+
+ /usr/bin/grep "^$drvname[ ]" $BASEDIR/etc/name_to_major > /dev/null 2>&1
+
+ if [ "$NO_CMD" = "" -a $? -ne 0 ]
+ then
+ eval $cmd
+ else
+ # entry already in name_to_major, add alias, class, minorperm
+ # if necessary
+ if [ $ADD_ALIAS = 1 ]
+ then
+ for i in $alias
+ do
+ /usr/bin/egrep "^$drvname[ ]+$i" $BASEDIR/etc/driver_aliases>/dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo "$drvname $i" >> $BASEDIR/etc/driver_aliases
+ fi
+ done
+ fi
+
+ if [ $ADD_CLASS = 1 ]
+ then
+ /usr/bin/egrep "^$drvname[ ]+$class( | |$)" $BASEDIR/etc/driver_classes > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo "$drvname\t$class" >> $BASEDIR/etc/driver_classes
+ fi
+ fi
+
+ if [ $ADD_MINOR = 1 ]
+ then
+ /usr/bin/grep "^$drvname:" $BASEDIR/etc/minor_perm > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ minorentry="$drvname:$minor"
+ echo $minorentry >> $BASEDIR/etc/minor_perm
+ fi
+ fi
+
+ fi
+
+
+}
+
+ check_add_drv -b "$BASEDIR" -i \
+ '"pci4040,1"
+ "pci4040,2"
+ "pci4040,3"
+ "pci4040,4"
+ "pci4040,5"
+ "pci4040,24"
+ "pci4040,25"
+ "pci4040,100"' \
+ ntxn
diff --git a/usr/src/pkgdefs/SUNWntxn/postremove b/usr/src/pkgdefs/SUNWntxn/postremove
new file mode 100644
index 0000000000..8c115417a7
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/postremove
@@ -0,0 +1,37 @@
+#!/sbin/sh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+BD=${BASEDIR:-/}
+if grep -w ntxn $BD/etc/name_to_major > /dev/null 2>&1
+then
+ rem_drv -b ${BD} ntxn
+ if [ $? -ne 0 ]
+ then
+ exit 1
+ fi
+fi
+exit 0
diff --git a/usr/src/pkgdefs/SUNWntxn/prototype_com b/usr/src/pkgdefs/SUNWntxn/prototype_com
new file mode 100644
index 0000000000..433b664b63
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/prototype_com
@@ -0,0 +1,50 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+#
+i pkginfo
+i copyright
+i depend
+i postinstall
+i postremove
+
+#
+#
+# NetXen 1Gb/10Gb NIC driver
+d none kernel 0755 root sys
+d none kernel/drv 0755 root sys
diff --git a/usr/src/pkgdefs/SUNWntxn/prototype_i386 b/usr/src/pkgdefs/SUNWntxn/prototype_i386
new file mode 100644
index 0000000000..7c82196efa
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWntxn/prototype_i386
@@ -0,0 +1,48 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+
+# NetXen 1Gb/10Gb NIC driver
+d none kernel/drv/amd64 0755 root sys
+f none kernel/drv/ntxn 0755 root sys
+f none kernel/drv/amd64/ntxn 0755 root sys
diff --git a/usr/src/tools/opensolaris/license-list b/usr/src/tools/opensolaris/license-list
index b31d0095c3..9629e6a3c0 100644
--- a/usr/src/tools/opensolaris/license-list
+++ b/usr/src/tools/opensolaris/license-list
@@ -166,3 +166,4 @@ usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.apple
usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.boris_popov
usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.bsd4
usr/src/lib/libsmbfs/smb/THIRDPARTYLICENSE.microsoft
+usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index f14d94be32..317efe009a 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1780,3 +1780,9 @@ ISCSI_INITIATOR_OBJS = chap.o iscsi_io.o iscsi_thread.o \
iscsi_sess.o radius_auth.o iscsi_crc.o \
iscsi_stats.o radius_packet.o iscsi_doorclt.o \
iscsi_targetparam.o utils.o
+
+#
+# ntxn 10Gb/1Gb NIC driver module
+#
+NTXN_OBJS = unm_nic_init.o unm_gem.o unm_nic_hw.o unm_ndd.o \
+ unm_nic_main.o unm_nic_isr.o unm_nic_ctx.o niu.o
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index f58ce32114..f131d68608 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -1017,6 +1017,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/ixgbe/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/ntxn/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/ipp/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1945,6 +1949,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/igb/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/ixgbe/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/ntxn/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/ipp/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE
new file mode 100644
index 0000000000..e65ae36a87
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE
@@ -0,0 +1,4 @@
+/*
+ * Copyright 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
diff --git a/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip
new file mode 100644
index 0000000000..ad8bb4d95c
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip
@@ -0,0 +1 @@
+ntxn - 10Gb/1Gb NIC driver for NetXen's Ethernet cards
diff --git a/usr/src/uts/common/io/ntxn/driver_info.h b/usr/src/uts/common/io/ntxn/driver_info.h
new file mode 100644
index 0000000000..b977f97fc9
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/driver_info.h
@@ -0,0 +1,67 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _driver_info_h_
+#define _driver_info_h_
+
+static const unm_brdinfo_t unm_boards[] = {
+ {UNM_BRDTYPE_P2_SB31_10G_CX4, 1, NX_P2_MN_TYPE_ROMIMAGE,
+ "XGb CX4"},
+ {UNM_BRDTYPE_P2_SB31_10G_HMEZ, 2, NX_P2_MN_TYPE_ROMIMAGE,
+ "XGb HMEZ"},
+ {UNM_BRDTYPE_P2_SB31_10G_IMEZ, 2, NX_P2_MN_TYPE_ROMIMAGE,
+ "XGb IMEZ"},
+ {UNM_BRDTYPE_P2_SB31_10G, 1, NX_P2_MN_TYPE_ROMIMAGE,
+ "XGb XFP"},
+ {UNM_BRDTYPE_P2_SB35_4G, 4, NX_P2_MN_TYPE_ROMIMAGE,
+ "Quad Gb"},
+ {UNM_BRDTYPE_P2_SB31_2G, 2, NX_P2_MN_TYPE_ROMIMAGE,
+ "Dual Gb"},
+ {UNM_BRDTYPE_P3_REF_QG, 4, NX_P3_MN_TYPE_ROMIMAGE,
+ "Reference card - Quad Gig "},
+ {UNM_BRDTYPE_P3_HMEZ, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Dual XGb HMEZ"},
+ {UNM_BRDTYPE_P3_10G_CX4_LP, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Dual XGb CX4 LP"},
+ {UNM_BRDTYPE_P3_4_GB, 4, NX_P3_CT_TYPE_ROMIMAGE,
+ "Quad Gig LP"},
+ {UNM_BRDTYPE_P3_IMEZ, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Dual XGb IMEZ"},
+ {UNM_BRDTYPE_P3_10G_SFP_PLUS, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Dual XGb SFP+ LP"},
+ {UNM_BRDTYPE_P3_10000_BASE_T, 1, NX_P3_CT_TYPE_ROMIMAGE,
+ "XGB 10G BaseT LP"},
+ {UNM_BRDTYPE_P3_XG_LOM, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Dual XGb LOM"},
+ {UNM_BRDTYPE_P3_4_GB_MM, 4, NX_P3_CT_TYPE_ROMIMAGE,
+ "NX3031 with Gigabit Ethernet"},
+ {UNM_BRDTYPE_P3_10G_CX4, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "Reference card - Dual CX4 Option"},
+ {UNM_BRDTYPE_P3_10G_XFP, 1, NX_P3_CT_TYPE_ROMIMAGE,
+ "Reference card - Single XFP Option"},
+ {UNM_BRDTYPE_P3_10G_TRP, 2, NX_P3_CT_TYPE_ROMIMAGE,
+ "NX3031 with 1/10 Gigabit Ethernet"},
+};
+
+#endif /* !_driver_info_h_ */
diff --git a/usr/src/uts/common/io/ntxn/message.h b/usr/src/uts/common/io/ntxn/message.h
new file mode 100644
index 0000000000..8e3b2b1383
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/message.h
@@ -0,0 +1,31 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __MESSAGE_H
+#define __MESSAGE_H
+
+typedef __uint64_t unm_msgword_t;
+typedef __uint32_t unm_halfmsgword_t;
+
+#endif /* !__MESSAGE_H */
diff --git a/usr/src/uts/common/io/ntxn/nic_cmn.h b/usr/src/uts/common/io/ntxn/nic_cmn.h
new file mode 100644
index 0000000000..b4cbeb4486
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/nic_cmn.h
@@ -0,0 +1,729 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef UNM_NIC_CMN_H
+#define UNM_NIC_CMN_H
+
+#ifndef sun
+#include "unm_nic_config.h"
+#include "unm_compiler_defs.h"
+#endif
+
+#define IP_ALIGNMENT_BYTES 2 /* make ip aligned on 16byteaddr */
+#define P2_MAX_MTU (8000)
+#define P3_MAX_MTU (9600)
+#define NX_ETHERMTU 1500
+#define NX_MAX_ETHERHDR 32 /* This contains some padding */
+
+#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU)
+#define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU)
+#define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU)
+
+#define MAX_RX_LRO_BUFFER_LENGTH ((8*1024) - 512)
+#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH -\
+ IP_ALIGNMENT_BYTES)
+
+/* Opcodes to be used with the commands */
+#define TX_ETHER_PKT 0x01
+/* The following opcodes are for IP checksum */
+#define TX_TCP_PKT 0x02
+#define TX_UDP_PKT 0x03
+#define TX_IP_PKT 0x04
+#define TX_TCP_LSO 0x05
+#define TX_IPSEC 0x06
+#define TX_IPSEC_CMD 0x07
+
+#define NETXEN_MAC_NOOP 0
+#define NETXEN_MAC_ADD 1
+#define NETXEN_MAC_DEL 2
+
+/* The following opcodes are for internal consumption. */
+#define UNM_CONTROL_OP 0x10
+#define PEGNET_REQUEST 0x11
+#define NX_HOST_REQUEST 0x13
+#define NX_NIC_REQUEST 0x14
+#define NX_NIC_LRO_REQUEST 0x15
+
+#define NX_MAC_EVENT 0x1
+
+enum {
+ NX_NIC_H2C_OPCODE_START = 0,
+ NX_NIC_H2C_OPCODE_CONFIG_RSS,
+ NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL,
+ NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE,
+ NX_NIC_H2C_OPCODE_CONFIG_LED,
+ NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS,
+ NX_NIC_H2C_OPCODE_CONFIG_L2_MAC,
+ NX_NIC_H2C_OPCODE_LRO_REQUEST,
+ NX_NIC_H2C_OPCODE_GET_SNMP_STATS,
+ NX_NIC_H2C_OPCODE_PROXY_START_REQUEST,
+ NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST,
+ NX_NIC_H2C_OPCODE_PROXY_SET_MTU,
+ NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE,
+ NX_H2P_OPCODE_GET_FINGER_PRINT_REQUEST,
+ NX_H2P_OPCODE_INSTALL_LICENSE_REQUEST,
+ NX_H2P_OPCODE_GET_LICENSE_CAPABILITY_REQUEST,
+ NX_NIC_H2C_OPCODE_GET_NET_STATS,
+ NX_NIC_H2C_OPCODE_LAST
+};
+
+#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
+#define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */
+#define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */
+
+#ifdef UNM_RSS
+#define RSS_CNTRL_CMD 0x20
+#endif
+#define MAX_NUM_CARDS 4
+#define MAX_NUM_PORTS 4 /* Deprecated. donot use this */
+#define MAX_NIU_PORTS MAX_NUM_PORTS
+#define PORT1 0
+#define PORT2 1
+#define PORT3 2
+#define PORT4 3
+
+
+#define DESC_CHAIN 0xFF /* descriptor command continuation */
+
+#define MAX_BUFFERS_PER_CMD 16
+#define MAX_BUFFERS_PER_DESC 4
+
+#define NX_P2_C0 0x24
+#define NX_P2_C1 0x25
+
+#define DUMMY_BUF_UNINIT 0x55555555
+#define DUMMY_BUF_INIT 0
+
+/*
+ * Following are the states of the Phantom. Phantom will set them and
+ * Host will read to check if the fields are correct.
+ */
+#define PHAN_INITIALIZE_START 0xff00
+#define PHAN_INITIALIZE_FAILED 0xffff
+#define PHAN_INITIALIZE_COMPLETE 0xff01
+
+/* Host writes the following to notify that it has done the init-handshake */
+#define PHAN_INITIALIZE_ACK 0xf00f
+
+/* Following defines will be used in the status descriptor */
+#define TX_ETHER_PKT_COMPLETE 0xB /* same for both commands */
+
+#define NUM_RCV_DESC_RINGS 3 /* No of Rcv Descriptor contexts */
+
+/* descriptor types */
+#define RCV_DESC_NORMAL 0x01
+#define RCV_DESC_JUMBO 0x02
+#define RCV_DESC_LRO 0x04
+#define RCV_DESC_NORMAL_CTXID 0
+#define RCV_DESC_JUMBO_CTXID 1
+#define RCV_DESC_LRO_CTXID 2
+
+#define RCV_DESC_TYPE(ID) \
+ ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : \
+ ((ID == RCV_DESC_LRO_CTXID) ? RCV_DESC_LRO : (RCV_DESC_NORMAL)))
+
+#define RCV_DESC_TYPE_NAME(ID) \
+ ((ID == RCV_DESC_JUMBO_CTXID) ? "Jumbo" : \
+ (ID == RCV_DESC_LRO_CTXID) ? "LRO" : \
+ (ID == RCV_DESC_NORMAL_CTXID) ? "Normal" : "Unknown")
+
+#define MAX_CMD_DESCRIPTORS 4096
+#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4)
+
+#define MAX_RCV_DESCRIPTORS 8192
+#define MAX_JUMBO_RCV_DESCRIPTORS 1024
+#define MAX_LRO_RCV_DESCRIPTORS 16
+
+#define NX_MAX_SUPPORTED_RDS_SIZE (32 * 1024)
+#define NX_MAX_SUPPORTED_JUMBO_RDS_SIZE (4 * 1024)
+
+#define PHAN_PEG_RCV_INITIALIZED 0xff01
+#define PHAN_PEG_RCV_START_INITIALIZE 0xff00
+
+#define get_next_index(index, length) ((((index) + 1) == length)?0:(index) +1)
+
+#define get_index_range(index, length, count) \
+ ((((index) + (count)) >= length)? \
+ (((index) + (count))-(length)):((index) + (count)))
+
+#define UNM_FLOW_TICKS_PER_SEC 2048
+#define UNM_FLOW_TO_TV_SHIFT_SEC 11
+#define UNM_FLOW_TO_TV_SHIFT_USEC 9
+#define UNM_FLOW_TICK_USEC (1000000ULL/UNM_FLOW_TICKS_PER_SEC)
+#define UNM_GLOBAL_TICKS_PER_SEC (4*UNM_FLOW_TICKS_PER_SEC)
+#define UNM_GLOBAL_TICK_USEC (1000000ULL/UNM_GLOBAL_TICKS_PER_SEC)
+
+
+/*
+ * Following data structures describe the descriptors that will be used.
+ * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
+ * we are doing LSO (above the 1500 size packet) only.
+ * This is an overhead but we need it. Let me know if you have questions.
+ */
+
+/*
+ * the size of reference handle been changed to 16 bits to pass the MSS fields
+ * for the LSO packet
+ */
+
+#define FLAGS_CHECKSUM_ENABLED 0x01
+#define FLAGS_LSO_ENABLED 0x02
+#define FLAGS_IPSEC_SA_ADD 0x04
+#define FLAGS_IPSEC_SA_DELETE 0x08
+#define FLAGS_VLAN_TAGGED 0x10
+
+#if UNM_CONF_PROCESSOR == UNM_CONF_X86
+
+#ifndef U64
+typedef unsigned long long U64;
+typedef uint32_t U32;
+typedef uint16_t U16;
+typedef uint8_t U8;
+#endif
+
+#endif
+
+#define NUM_SUPPORTED_RINGSETS 4
+#define MAX_RING_CTX 4
+#define UNM_CTX_SIGNATURE 0xdee0
+#define UNM_CTX_RESET 0xbad0
+#define UNM_CTX_D3_RESET 0xacc0
+
+/* define opcode for ctx_msg */
+#define RX_PRODUCER 0
+#define RX_PRODUCER_JUMBO 1
+#define RX_PRODUCER_LRO 2
+#define TX_PRODUCER 3
+#define UPDATE_STATUS_CONSUMER 4
+#define RESET_CTX 5
+
+#define NUM_DB_CODE 6
+
+#define UNM_RCV_PRODUCER(ringid) (ringid)
+#define UNM_CMD_PRODUCER TX_PRODUCER
+#define UNM_RCV_STATUS_CONSUMER UPDATE_STATUS_CONSUMER
+
+typedef struct __msg
+{
+ __uint32_t PegId:2, // 0x2 for tx and 01 for rx.
+ privId:1, // must be 1
+ Count:15, // for doorbell
+ CtxId:10, // Ctx_id
+ Opcode:4; /* opcode */
+}ctx_msg, CTX_MSG, *PCTX_MSG;
+
+typedef struct __int_msg
+{
+ __uint32_t Count:18, // INT
+ ConsumerIdx:10,
+ CtxId:4; // Ctx_id
+
+}int_msg, INT_MSG, *PINT_MSG;
+
+/* For use in CRB_MPORT_MODE */
+#define MPORT_SINGLE_FUNCTION_MODE 0x1111
+#define MPORT_MULTI_FUNCTION_MODE 0x2222
+
+typedef struct _RcvContext
+{
+ __uint32_t RcvRingAddrLo;
+ __uint32_t RcvRingAddrHi;
+ __uint32_t RcvRingSize;
+ __uint32_t Rsrv;
+}RcvContext;
+
+typedef struct PREALIGN(64) _RingContext
+{
+
+ /* one command ring */
+ __uint64_t CMD_CONSUMER_OFFSET;
+ __uint32_t CmdRingAddrLo;
+ __uint32_t CmdRingAddrHi;
+ __uint32_t CmdRingSize;
+ __uint32_t Rsrv;
+
+ /* three receive rings */
+ RcvContext RcvContext[3];
+
+ /* one status ring */
+ __uint32_t StsRingAddrLo;
+ __uint32_t StsRingAddrHi;
+ __uint32_t StsRingSize;
+
+ __uint32_t CtxId;
+
+ __uint64_t D3_STATE_REGISTER;
+ __uint32_t DummyDmaAddrLo;
+ __uint32_t DummyDmaAddrHi;
+
+}POSTALIGN(64) RingContext, RING_CTX, *PRING_CTX;
+
+#ifdef UNM_RSS
+/*
+ * RSS_SreInfo{} has the information for SRE to calculate the hash value
+ * Will be passed by the host=> as part of comd descriptor...
+ */
+
+#if UNM_CONF_PROCESSOR == UNM_CONF_X86
+typedef struct _RSS_SreInfo {
+ U32 HashKeySize;
+ U32 HashInformation;
+ char key[40];
+}RSS_SreInfo;
+#endif
+
+/*
+ * The following Descriptor is used to send RSS commands to the
+ * PEG.... to be do the SRE registers..
+ */
+typedef struct PREALIGN(64) _rssCmdDesc
+{
+
+ /*
+ * To keep the opcode at the same location as
+ * the cmdDescType0, we will have to breakup the key into
+ * 2 areas.... Dont like it but for now will do... FSL
+ */
+
+#if UNM_CONF_PROCESSOR == UNM_CONF_X86
+ U8 Key0[16];
+
+ U64 HashMethod:32,
+ HashKeySize:8,
+ Unused: 16,
+ opcode:8;
+
+ U8 Key1[24];
+ U64 Unused1;
+ U64 Unused2;
+#else
+
+ unm_msgword_t Key0[2];
+ unm_halfmsgword_t HashMethod;
+ unm_halfmsgword_t
+ HashKeySize:8,
+ Unused:16,
+ opcode:8;
+
+ unm_msgword_t Key1[3];
+ unm_msgword_t Unused1;
+ unm_msgword_t Unused2;
+
+#endif
+
+} POSTALIGN(64) rssCmdDesc_t;
+
+
+#endif /* UNM_RSS */
+
+
+typedef struct PREALIGN(64) cmdDescType0
+{
+ union {
+ struct {
+ __uint32_t tcpHdrOffset:8, /* For LSO only */
+ ipHdrOffset:8, // For LSO only
+ flags:7, /* as defined above */
+ /* This location/size must not change... */
+ opcode:6,
+ Unused:3;
+ /* total number of segments (buffers */
+ __uint32_t numOfBuffers:8,
+ /* for this packet. (could be more than 4) */
+
+ /* Total size of the packet */
+ totalLength:24;
+ }s1;
+ __uint64_t word0;
+ }u1;
+
+ union {
+ struct {
+ __uint32_t AddrLowPart2;
+ __uint32_t AddrHighPart2;
+ }s1;
+ __uint64_t AddrBuffer2;
+ __uint64_t word1;
+ }u2;
+
+ union {
+ struct {
+ /* changed to U16 to add mss */
+ __uint32_t referenceHandle:16,
+ /* passed by NDIS_PACKET for LSO */
+ mss:16;
+ __uint32_t port:4,
+ ctx_id:4,
+ /* LSO only : MAC+IP+TCP Hdr size */
+ totalHdrLength:8,
+ /* IPSec offoad only */
+ connID:16;
+ }s1;
+ __uint64_t word2;
+ }u3;
+
+ union {
+ struct {
+ __uint32_t AddrLowPart3;
+ __uint32_t AddrHighPart3;
+ }s1;
+ __uint64_t AddrBuffer3;
+ __uint64_t word3;
+ }u4;
+
+ union {
+ struct {
+ __uint32_t AddrLowPart1;
+ __uint32_t AddrHighPart1;
+ }s1;
+ __uint64_t AddrBuffer1;
+ __uint64_t word4;
+ }u5;
+
+ union {
+ struct {
+ __uint32_t buffer1Length:16,
+ buffer2Length:16;
+ __uint32_t buffer3Length:16,
+ buffer4Length:16;
+ }s1;
+ __uint64_t word5;
+ }u6;
+
+ union {
+ struct {
+ __uint32_t AddrLowPart4;
+ __uint32_t AddrHighPart4;
+ }s1;
+ __uint64_t AddrBuffer4;
+ __uint64_t word6;
+ }u7;
+
+ __uint64_t unused;
+
+} POSTALIGN(64) cmdDescType0_t;
+
+/* Note: sizeof(rcvDesc) should always be a mutliple of 2 */
+typedef struct rcvDesc
+{
+ __uint32_t referenceHandle:16,
+ flags:16;
+ __uint32_t
+ /* allocated buffer length (usually 2K) */
+ bufferLength:32;
+ __uint64_t AddrBuffer;
+} rcvDesc_t;
+
+/* for status field in statusDesc_t */
+#define STATUS_NEED_CKSUM (1)
+#define STATUS_CKSUM_OK (2)
+#define STATUS_CKSUM_NOT_OK (3)
+
+/* owner bits of statusDesc_t */
+#define STATUS_OWNER_HOST (1ULL)
+#define STATUS_OWNER_PHANTOM (2ULL)
+#define HOST_STATUS_DESC ((STATUS_OWNER_HOST) << 48)
+#define PHANTOM_STATUS_DESC ((STATUS_OWNER_PHANTOM) << 48)
+
+#define UNM_PROT_IP (1)
+#define UNM_PROT_UNKNOWN (0)
+
+/* LRO specific bits of statusDesc_t */
+#define LRO_LAST_FRAG (1)
+#define LRO_NORMAL_FRAG (0)
+#define LRO_LAST_FRAG_DESC ((LRO_LAST_FRAG)<<63)
+#define LRO_NORMAL_FRAG_DESC ((LRO_NORMAL_FRAG)<<63)
+
+typedef struct PREALIGN(16) statusDesc {
+ union {
+ struct {
+ /* initially to be used but noe now */
+ __uint32_t port:4,
+ /* completion status may not have use */
+ status:4,
+ /* type/index of descriptor ring */
+ type:4,
+ /* NIC mode...no use yet */
+ totalLength:16,
+ /* handle for the associated packet */
+ referenceHandle_lo:4;
+ /* handle for the associated packet */
+ __uint32_t referenceHandle_hi:12,
+ /* Pkt protocol */
+ prot:4,
+ pkt_offset:5,
+/*
+ * This indicates the num of descriptors part of this descriptor chain.
+ */
+ descCnt:3,
+ owner:2,
+ opcode:6;
+
+ __uint32_t HashValue;
+ __uint16_t vlan;
+ __uint8_t HashType;
+
+ union {
+ /*
+ * For LRO count is set
+ * Last LRO fragment is set when it is
+ * the last frag as the name says.
+ */
+ __uint8_t lro_frag:7, last_lro_frag:1;
+
+ /*
+ * Used to indicate direction in case
+ * of captured packets. Egress will
+ * contain EPG input, while ingress
+ * contains an skb copy.
+ */
+#define NX_CAP_DIRN_OUT 1
+#define NX_CAP_DIRN_IN 2
+ __uint8_t direction;
+
+ /*
+ * Currently for Legacy this is 0.
+ */
+ __uint8_t nr_frags;
+ }u11;
+
+ }s1;
+ __uint64_t body[2];
+ }u1;
+
+} POSTALIGN(16) statusDesc_t;
+
+
+#define STATUS_OWNER_NAME(sd) \
+ (((sd)->u1.s1.owner == STATUS_OWNER_HOST) ? "Host" : "Phantom")
+
+#ifdef UNM_IPSECOFFLOAD
+
+#define MAX_IPSEC_SAS 1024
+#define RECEIVE_IPSEC_SA_BASE 0x8000
+
+/*
+ * IPSEC related structures and defines
+ */
+
+/* Values for DIrFlag in the ipsec_sa_t structure below: */
+#define UNM_IPSEC_SA_DIR_INBOUND 1
+#define UNM_IPSEC_SA_DIR_OUTBOUND 2
+
+/* Values for Operation Field below: */
+#define UNM_IPSEC_SA_AUTHENTICATE 1
+#define UNM_IPSEC_SA_ENDECRYPT 2
+
+/* COnfidential Algorithm Types: */
+#define UNM_IPSEC_CONF_NONE 0 // NULL encryption?
+#define UNM_IPSEC_CONF_DES 1
+#define UNM_IPSEC_CONF_RESERVED 2
+#define UNM_IPSEC_CONF_3DES 3
+
+/* Integrity algorithm (AH) types: */
+#define UNM_IPSEC_INTEG_NONE 0
+#define UNM_IPSEC_INTEG_MD5 1
+#define UNM_IPSEC_INTEG_SHA1 2
+
+#define UNM_PROTOCOL_OFFSET 0x9 // from ip header begin, in bytes
+#define UNM_PKT_TYPE_AH 0x33
+#define UNM_PKT_TYPE_ESP 0x32
+
+
+/* 96 bits of output for MD5/SHA1 algorithms */
+#define UNM_AHOUTPUT_LENGTH 12
+/*
+ * 8 bytes (64 bits) of ICV value for each block of DES_CBC
+ * at the begin of ESP payload
+ */
+#define UNM_DES_ICV_LENGTH 8
+
+#if UNM_CONF_PROCESSOR == UNM_CONF_X86
+
+typedef struct PREALIGN(512) s_ipsec_sa {
+ U32 SrcAddr;
+ U32 SrcMask;
+ U32 DestAddr;
+ U32 DestMask;
+ U32 Protocol:8,
+ DirFlag:4,
+ IntegCtxInit:2,
+ ConfCtxInit:2,
+ No_of_keys:8,
+ Operation:8;
+ U32 IntegAlg:8,
+ IntegKeyLen:8,
+ ConfAlg:8,
+ ConfAlgKeyLen:8;
+ U32 SAIndex;
+ U32 SPI_Id;
+ U64 Key1[124];
+} POSTALIGN(512) unm_ipsec_sa_t;
+
+#else
+
+typedef struct PREALIGN(512) s_ipsec_sa {
+ unm_halfmsgword_t SrcAddr;
+ unm_halfmsgword_t SrcMask;
+ unm_halfmsgword_t DestAddr;
+ unm_halfmsgword_t DestMask;
+ unm_halfmsgword_t Protocol:8,
+ DirFlag:4,
+ IntegCtxInit:2,
+ ConfCtxInit:2,
+ No_of_keys:8,
+ Operation:8;
+ unm_halfmsgword_t IntegAlg:8,
+ IntegKeyLen:8,
+ ConfAlg:8,
+ ConfAlgKeyLen:8;
+ unm_halfmsgword_t SAIndex:32;
+ unm_halfmsgword_t SPI_Id:32;
+ /* to round up to 1K of structure */
+ unm_msgword_t Key1[124];
+} POSTALIGN(512) unm_ipsec_sa_t;
+
+#endif /* NOT-X86 */
+
+/* Other common header formats that may be needed */
+
+typedef struct _unm_ip_header_s {
+ U32 HdrVer:8,
+ diffser:8,
+ TotalLength:16;
+ U32 ipId:16,
+ flagfrag:16;
+ U32 TTL:8,
+ Protocol:8,
+ Chksum:16;
+ U32 srcaddr;
+ U32 destaddr;
+} unm_ip_header_t;
+
+typedef struct _unm_ah_header_s {
+ U32 NextProto:8,
+ length:8,
+ reserved:16;
+ U32 SPI;
+ U32 seqno;
+ U16 ICV;
+ U16 ICV1;
+ U16 ICV2;
+ U16 ICV3;
+ U16 ICV4;
+ U16 ICV5;
+} unm_ah_header_t;
+
+typedef struct _unm_esp_hdr_s {
+ U32 SPI;
+ U32 seqno;
+} unm_esp_hdr_t;
+
+#endif /* UNM_IPSECOFFLOAD */
+
+/*
+ * Defines for various loop counts. These determine the behaviour of the
+ * system. The classic tradeoff between latency and throughput.
+ */
+
+/*
+ * MAX_DMA_LOOPCOUNT : After how many interations do we start the dma for
+ * the status descriptors.
+ */
+#define MAX_DMA_LOOPCOUNT (32)
+
+/*
+ * MAX_TX_DMA_LOOP_COUNT : After how many interations do we start the dma for
+ * the command descriptors.
+ */
+#define MAX_TX_DMA_LOOP_COUNT 1000
+
+/*
+ * MAX_RCV_BUFS : Max number Rx packets that can be buffered before DMA/INT
+ */
+#define MAX_RCV_BUFS (4096)
+
+/*
+ * XXX;shouldnt be exposed in nic_cmn.h
+ * DMA_MAX_RCV_BUFS : Max number Rx packets that can be buffered before DMA
+ */
+#define DMA_MAX_RCV_BUFS (4096)
+
+/*
+ * XXX;shouldnt be exposed in nic_cmn.h
+ * MAX_DMA_ENTRIES : Max number Rx dma entries can be in dma list
+ */
+#define MAX_DMA_ENTRIES (4096)
+
+
+/*
+ * MAX_INTR_LOOPCOUNT : After how many iterations do we interrupt the
+ * host ?
+ */
+#define MAX_INTR_LOOPCOUNT (1024)
+
+/*
+ * XMIT_LOOP_THRESHOLD : How many times do we spin before we process the
+ * transmit buffers.
+ */
+#define XMIT_LOOP_THRESHOLD 0x20
+
+/*
+ * XMIT_DESC_THRESHOLD : How many descriptors pending before we process
+ * the descriptors.
+ */
+#define XMIT_DESC_THRESHOLD 0x4
+
+/*
+ * TX_DMA_THRESHOLD : When do we start the dma of the command descriptors.
+ * We need these number of command descriptors, or we need to exceed the
+ * loop count. P1 only.
+ */
+#define TX_DMA_THRESHOLD 16
+
+#if defined(UNM_IP_FILTER)
+/*
+ * Commands. Must match the definitions in nic/Linux/include/unm_nic_ioctl.h
+ */
+enum {
+ UNM_IP_FILTER_CLEAR = 1,
+ UNM_IP_FILTER_ADD,
+ UNM_IP_FILTER_DEL,
+ UNM_IP_FILTER_SHOW
+};
+
+#define MAX_FILTER_ENTRIES 16
+
+typedef struct {
+ __int32_t count;
+ __uint32_t ip_addr[15];
+} unm_ip_filter_t;
+#endif /* UNM_IP_FILTER */
+
+enum {
+ UNM_RCV_PEG_0 = 0,
+ UNM_RCV_PEG_1
+};
+
+#endif /* !UNM_NIC_CMN_H */
diff --git a/usr/src/uts/common/io/ntxn/nic_phan_reg.h b/usr/src/uts/common/io/ntxn/nic_phan_reg.h
new file mode 100644
index 0000000000..356d5d78d3
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/nic_phan_reg.h
@@ -0,0 +1,161 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef NIC_PHAN_REG_H
+#define NIC_PHAN_REG_H
+
+#define NIC_CRB_BASE UNM_CAM_RAM(0x200)
+#define NIC_CRB_BASE_2 UNM_CAM_RAM(0x700)
+#define UNM_NIC_REG(X) (NIC_CRB_BASE+(X))
+#define UNM_NIC_REG_2(X) (NIC_CRB_BASE_2+(X))
+
+#define CRB_CUT_THRU_PAGE_SIZE UNM_CAM_RAM(0x170)
+
+#define CRB_CMD_PRODUCER_OFFSET UNM_NIC_REG(0x08)
+#define CRB_CMD_CONSUMER_OFFSET UNM_NIC_REG(0x0c)
+/* C0 EPG BUG */
+#define CRB_PAUSE_ADDR_LO UNM_NIC_REG(0x10)
+#define CRB_PAUSE_ADDR_HI UNM_NIC_REG(0x14)
+#define NX_CDRP_CRB_OFFSET UNM_NIC_REG(0x18)
+#define NX_ARG1_CRB_OFFSET UNM_NIC_REG(0x1c)
+#define NX_ARG2_CRB_OFFSET UNM_NIC_REG(0x20)
+#define NX_ARG3_CRB_OFFSET UNM_NIC_REG(0x24)
+#define NX_SIGN_CRB_OFFSET UNM_NIC_REG(0x28)
+#define CRB_CMDPEG_CMDRING UNM_NIC_REG(0x38)
+#define CRB_HOST_DUMMY_BUF_ADDR_HI UNM_NIC_REG(0x3c)
+#define CRB_HOST_DUMMY_BUF_ADDR_LO UNM_NIC_REG(0x40)
+#define CRB_CMDPEG_STATE UNM_NIC_REG(0x50)
+/* interrupt coalescing */
+#define CRB_GLOBAL_INT_COAL UNM_NIC_REG(0x64)
+#define CRB_INT_COAL_MODE UNM_NIC_REG(0x68)
+#define CRB_MAX_RCV_BUFS UNM_NIC_REG(0x6c)
+#define CRB_TX_INT_THRESHOLD UNM_NIC_REG(0x70)
+#define CRB_RX_PKT_TIMER UNM_NIC_REG(0x74)
+#define CRB_TX_PKT_TIMER UNM_NIC_REG(0x78)
+#define CRB_RX_PKT_CNT UNM_NIC_REG(0x7c)
+#define CRB_RX_TMR_CNT UNM_NIC_REG(0x80)
+#define CRB_RCV_INTR_COUNT UNM_NIC_REG(0x84)
+/* XG Link status */
+#define CRB_XG_STATE UNM_NIC_REG(0x94)
+/* XG PF Link status */
+#define CRB_XG_STATE_P3 UNM_NIC_REG(0x98)
+/* Debug -performance */
+#define CRB_TX_STATE UNM_NIC_REG(0xac)
+#define CRB_TX_COUNT UNM_NIC_REG(0xb0)
+#define CRB_RX_STATE UNM_NIC_REG(0xb4)
+#define CRB_RX_PERF_DEBUG_1 UNM_NIC_REG(0xb8)
+/* LRO On/OFF */
+#define CRB_RX_LRO_CONTROL UNM_NIC_REG(0xbc)
+/* Multiport Mode */
+#define CRB_MPORT_MODE UNM_NIC_REG(0xc4)
+#define CRB_INT_VECTOR UNM_NIC_REG(0xd4)
+#define CRB_PF_LINK_SPEED_1 UNM_NIC_REG(0xe8)
+#define CRB_PF_LINK_SPEED_2 UNM_NIC_REG(0xec)
+#define CRB_HOST_DUMMY_BUF UNM_NIC_REG(0xfc)
+
+#define CRB_SCRATCHPAD_TEST UNM_NIC_REG(0x280)
+
+#define CRB_RCVPEG_STATE UNM_NIC_REG(0x13c)
+
+/* 12 registers to store MAC addresses for 8 PCI functions */
+#define CRB_MAC_BLOCK_START UNM_CAM_RAM(0x1c0)
+
+#define CRB_CMD_PRODUCER_OFFSET_1 UNM_NIC_REG(0x1ac)
+#define CRB_CMD_CONSUMER_OFFSET_1 UNM_NIC_REG(0x1b0)
+#define CRB_TEMP_STATE UNM_NIC_REG(0x1b4)
+#define CRB_CMD_PRODUCER_OFFSET_2 UNM_NIC_REG(0x1b8)
+#define CRB_CMD_CONSUMER_OFFSET_2 UNM_NIC_REG(0x1bc)
+
+#define CRB_CMD_PRODUCER_OFFSET_3 UNM_NIC_REG(0x1d0)
+#define CRB_CMD_CONSUMER_OFFSET_3 UNM_NIC_REG(0x1d4)
+/* sw int status/mask registers */
+#define CRB_SW_INT_MASK_OFFSET_0 0x1d8
+#define CRB_SW_INT_MASK_OFFSET_1 0x1e0
+#define CRB_SW_INT_MASK_OFFSET_2 0x1e4
+#define CRB_SW_INT_MASK_OFFSET_3 0x1e8
+#define CRB_SW_INT_MASK_OFFSET_4 0x450
+#define CRB_SW_INT_MASK_OFFSET_5 0x454
+#define CRB_SW_INT_MASK_OFFSET_6 0x458
+#define CRB_SW_INT_MASK_OFFSET_7 0x45c
+#define CRB_SW_INT_MASK_0 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_0)
+#define CRB_SW_INT_MASK_1 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_1)
+#define CRB_SW_INT_MASK_2 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_2)
+#define CRB_SW_INT_MASK_3 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_3)
+#define CRB_SW_INT_MASK_4 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_4)
+#define CRB_SW_INT_MASK_5 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_5)
+#define CRB_SW_INT_MASK_6 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_6)
+#define CRB_SW_INT_MASK_7 UNM_NIC_REG(CRB_SW_INT_MASK_OFFSET_7)
+
+#define CRB_NIC_DEBUG_STRUCT_BASE UNM_NIC_REG(0x288)
+
+/*
+ * capabilities register, can be used to selectively enable/disable features
+ * for backward compability
+ */
+#define CRB_NIC_CAPABILITIES_HOST UNM_NIC_REG(0x1a8)
+#define CRB_NIC_MSI_MODE_HOST UNM_NIC_REG(0x270)
+#define INTR_SCHEME_PERPORT 0x1
+#define MSI_MODE_MULTIFUNC 0x1
+
+#define CRB_EPG_QUEUE_BUSY_COUNT UNM_NIC_REG(0x200)
+
+#define CRB_V2P_0 UNM_NIC_REG(0x290)
+#define CRB_V2P_1 UNM_NIC_REG(0x294)
+#define CRB_V2P_2 UNM_NIC_REG(0x298)
+#define CRB_V2P_3 UNM_NIC_REG(0x29c)
+#define CRB_V2P(port) (CRB_V2P_0+((port)*4))
+#define CRB_DRIVER_VERSION UNM_NIC_REG(0x2a0)
+
+#define CRB_CNT_DBG1 UNM_NIC_REG(0x2a4)
+#define CRB_CNT_DBG2 UNM_NIC_REG(0x2a8)
+#define CRB_CNT_DBG3 UNM_NIC_REG(0x2ac)
+
+ /*
+ * Driver must set the version number register as follows:
+ * (major << 16) | (minor << 8) | (subminor)
+ */
+
+/* last -> 0x2a0 */
+
+/* Upper 16 bits of CRB_TEMP_STATE:temperature value. Lower 16 bits: state */
+#define nx_get_temp_val(x) ((x) >> 16)
+#define nx_get_temp_state(x) ((x) & 0xffff)
+#define nx_encode_temp(val, state) (((val) << 16) | (state))
+
+#define lower32(x) ((__uint32_t)((x) & 0xffffffff))
+#define upper32(x) ((__uint32_t)(((unsigned long long)(x) >> 32) & \
+ 0xffffffff))
+
+/*
+ * Temperature control.
+ */
+enum {
+ NX_TEMP_NORMAL = 0x1, /* Normal operating range */
+ NX_TEMP_WARN, /* Sound alert, temperature getting high */
+ NX_TEMP_PANIC /* Fatal error, hardware has shut down. */
+};
+
+#define D3_CRB_REG_FUN2 (UNM_PCIX_PS_REG(0x2084))
+#define D3_CRB_REG_FUN3 (UNM_PCIX_PS_REG(0x3084))
+#endif /* NIC_PHAN_REG_H */
diff --git a/usr/src/uts/common/io/ntxn/niu.c b/usr/src/uts/common/io/ntxn/niu.c
new file mode 100644
index 0000000000..2403d8ec65
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/niu.c
@@ -0,0 +1,689 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+
+#include <sys/pci.h>
+
+#include "unm_inc.h"
+#include "unm_nic.h"
+
+static long phy_lock_timeout = 100000000;
+
+static int phy_lock(struct unm_adapter_s *adapter)
+{
+ u32 done = 0;
+ int timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore3 from PCI HW block */
+ adapter->unm_nic_pci_read_immediate(adapter,
+ UNM_PCIE_REG(PCIE_SEM3_LOCK), &done);
+ if (done == 1)
+ break;
+ if (timeout >= phy_lock_timeout)
+ return (-1);
+ timeout++;
+ }
+
+ adapter->unm_crb_writelit_adapter(adapter, UNM_PHY_LOCK_ID,
+ PHY_LOCK_DRIVER);
+ return (0);
+}
+
+static void
+phy_unlock(struct unm_adapter_s *adapter)
+{
+ u32 val;
+
+ /* release semaphore3 */
+ adapter->unm_nic_pci_read_immediate(adapter,
+ UNM_PCIE_REG(PCIE_SEM3_UNLOCK), &val);
+}
+
+/*
+ * unm_niu_gbe_phy_read - read a register from the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ * Individual phys are addressed as follows:
+ * [15:8] phy id
+ * [7:0] register number
+ *
+ * Returns: 0 success
+ * -1 error
+ *
+ */
+long
+unm_niu_gbe_phy_read(struct unm_adapter_s *adapter, long reg,
+ unm_crbword_t *readval)
+{
+ long phy = adapter->physical_port;
+ unm_niu_gb_mii_mgmt_address_t address;
+ unm_niu_gb_mii_mgmt_command_t command;
+ unm_niu_gb_mii_mgmt_indicators_t status;
+
+ long timeout = 0;
+ long result = 0;
+ long restore = 0;
+ unm_niu_gb_mac_config_0_t mac_cfg0;
+
+ if (phy_lock(adapter) != 0)
+ return (-1);
+
+ /*
+ * MII mgmt all goes through port 0 MAC interface, so it cannot be
+ * in reset
+ */
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(0),
+ &mac_cfg0, 4);
+ if (mac_cfg0.soft_reset) {
+ unm_niu_gb_mac_config_0_t temp;
+ *(unm_crbword_t *)&temp = 0;
+ temp.tx_reset_pb = 1;
+ temp.rx_reset_pb = 1;
+ temp.tx_reset_mac = 1;
+ temp.rx_reset_mac = 1;
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_GB_MAC_CONFIG_0(0), &temp, 4);
+ restore = 1;
+ }
+
+ *(unm_crbword_t *)&address = 0;
+ address.reg_addr = (unm_crbword_t)reg;
+ address.phy_addr = (unm_crbword_t)phy;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_ADDR(0),
+ &address, 4);
+
+ *(unm_crbword_t *)&command = 0; /* turn off any prior activity */
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_COMMAND(0),
+ &command, 4);
+
+ /* send read command */
+ command.read_cycle = 1;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_COMMAND(0),
+ &command, 4);
+
+ *(unm_crbword_t *)&status = 0;
+ do {
+ adapter->unm_nic_hw_read_wx(adapter,
+ UNM_NIU_GB_MII_MGMT_INDICATE(0), &status, 4);
+ timeout++;
+ } while ((status.busy || status.notvalid) &&
+ (timeout++ < UNM_NIU_PHY_WAITMAX));
+
+ if (timeout < UNM_NIU_PHY_WAITMAX) {
+ adapter->unm_nic_hw_read_wx(adapter,
+ UNM_NIU_GB_MII_MGMT_STATUS(0), readval, 4);
+ result = 0;
+ } else
+ result = -1;
+
+ if (restore)
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4);
+
+ phy_unlock(adapter);
+
+ return (result);
+}
+
+/*
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+unm_niu_macaddr_get(struct unm_adapter_s *adapter, unsigned char *addr)
+{
+ __uint64_t result;
+ int phy = adapter->physical_port;
+
+ if (addr == NULL)
+ return (-1);
+ if ((phy < 0) || (phy > 3))
+ return (-1);
+
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ if (adapter->curr_window != 0) {
+ adapter->unm_nic_pci_change_crbwindow(adapter, 0);
+ }
+
+ result = UNM_NIC_PCI_READ_32((void *)pci_base_offset(adapter,
+ UNM_NIU_GB_STATION_ADDR_1(phy))) >> 16;
+ result |= ((uint64_t)UNM_NIC_PCI_READ_32((void *)pci_base_offset(
+ adapter, UNM_NIU_GB_STATION_ADDR_0(phy)))) << 16;
+
+ (void) memcpy(addr, &result, sizeof (unm_ethernet_macaddr_t));
+
+ adapter->unm_nic_pci_change_crbwindow(adapter, 1);
+
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+
+ return (0);
+}
+
+/*
+ * Set the station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+unm_niu_macaddr_set(struct unm_adapter_s *adapter, unm_ethernet_macaddr_t addr)
+{
+ unm_crbword_t temp = 0;
+ int phy = adapter->physical_port;
+
+ if ((phy < 0) || (phy > 3))
+ return (-1);
+
+ (void) memcpy(&temp, addr, 2);
+ temp <<= 16;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_STATION_ADDR_1(phy),
+ &temp, 4);
+ temp = 0;
+ (void) memcpy(&temp, ((__uint8_t *)addr)+2, sizeof (unm_crbword_t));
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_STATION_ADDR_0(phy),
+ &temp, 4);
+ return (0);
+}
+
+/* Enable a GbE interface */
+/* ARGSUSED */
+native_t unm_niu_enable_gbe_port(struct unm_adapter_s *adapter,
+ unm_niu_gbe_ifmode_t mode_dont_care)
+{
+ unm_niu_gb_mac_config_0_t mac_cfg0;
+ unm_niu_gb_mac_config_1_t mac_cfg1;
+ unm_niu_gb_mii_mgmt_config_t mii_cfg;
+ native_t port = adapter->physical_port;
+ int zero = 0;
+ int one = 1;
+ u32 port_mode = 0;
+
+ mode_dont_care = 0;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS)) {
+ return (-1);
+ }
+
+ if (adapter->link_speed != MBPS_10 &&
+ adapter->link_speed != MBPS_100 &&
+ adapter->link_speed != MBPS_1000) {
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+/*
+ * Do NOT fail this call because the cable is unplugged.
+ * Updated when the link comes up...
+ */
+ adapter->link_speed = MBPS_1000;
+ } else {
+ return (-1);
+ }
+ }
+
+ port_mode = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_PORT_MODE_ADDR);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ *(unm_crbword_t *)&mac_cfg0 = 0x0000003f;
+ *(unm_crbword_t *)&mac_cfg1 = 0x0000f2df;
+ unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_0(port), &mac_cfg0,
+ adapter);
+ unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_1(port), &mac_cfg1,
+ adapter);
+ } else {
+ *(unm_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.soft_reset = 1;
+ unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
+ adapter);
+
+ *(unm_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.tx_enable = 1;
+ mac_cfg0.rx_enable = 1;
+ mac_cfg0.rx_flowctl = 0;
+ mac_cfg0.tx_reset_pb = 1;
+ mac_cfg0.rx_reset_pb = 1;
+ mac_cfg0.tx_reset_mac = 1;
+ mac_cfg0.rx_reset_mac = 1;
+
+ unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
+ adapter);
+
+ *(unm_crbword_t *)&mac_cfg1 = 0;
+ mac_cfg1.preamblelen = 0xf;
+ mac_cfg1.duplex = 1;
+ mac_cfg1.crc_enable = 1;
+ mac_cfg1.padshort = 1;
+ mac_cfg1.checklength = 1;
+ mac_cfg1.hugeframes = 1;
+
+ switch (adapter->link_speed) {
+ case MBPS_10:
+ case MBPS_100: /* Fall Through */
+ mac_cfg1.intfmode = 1;
+ unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_1
+ (port), &mac_cfg1, adapter);
+
+ /* set mii mode */
+ unm_crb_write_adapter(
+ UNM_NIU_GB0_GMII_MODE+(port<<3),
+ &zero, adapter);
+ unm_crb_write_adapter(
+ UNM_NIU_GB0_MII_MODE+(port<< 3),
+ &one, adapter);
+ break;
+
+ case MBPS_1000:
+ mac_cfg1.intfmode = 2;
+ unm_crb_write_adapter(
+ UNM_NIU_GB_MAC_CONFIG_1(port),
+ &mac_cfg1, adapter);
+
+ /* set gmii mode */
+ unm_crb_write_adapter(
+ UNM_NIU_GB0_MII_MODE+(port << 3),
+ &zero, adapter);
+ unm_crb_write_adapter(
+ UNM_NIU_GB0_GMII_MODE+(port << 3),
+ &one, adapter);
+ break;
+
+ default:
+ /* Will not happen */
+ break;
+ }
+
+ *(unm_crbword_t *)&mii_cfg = 0;
+ mii_cfg.clockselect = 7;
+ unm_crb_write_adapter(UNM_NIU_GB_MII_MGMT_CONFIG(port),
+ &mii_cfg, adapter);
+
+ *(unm_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.tx_enable = 1;
+ mac_cfg0.rx_enable = 1;
+ mac_cfg0.tx_flowctl = 0;
+ mac_cfg0.rx_flowctl = 0;
+ unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg0, adapter);
+ }
+
+ return (0);
+}
+
+/* Disable a GbE interface */
+native_t
+unm_niu_disable_gbe_port(struct unm_adapter_s *adapter)
+{
+ native_t port = adapter->physical_port;
+ unm_niu_gb_mac_config_0_t mac_cfg0;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
+ return (-1);
+
+ *(unm_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.soft_reset = 1;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 0);
+ else
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 4);
+ return (0);
+}
+
+/* Disable an XG interface */
+native_t
+unm_niu_disable_xg_port(struct unm_adapter_s *adapter)
+{
+ native_t port = adapter->physical_port;
+ unm_niu_xg_mac_config_0_t mac_cfg;
+
+ *(unm_crbword_t *)&mac_cfg = 0;
+ mac_cfg.soft_reset = 1;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (port != 0)
+ return (-1);
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0,
+ &mac_cfg, 4);
+ } else {
+ if ((port < 0) || (port >= UNM_NIU_MAX_XG_PORTS))
+ return (-1);
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
+ (port * 0x10000), &mac_cfg, 4);
+ }
+ return (0);
+}
+
+
+/* Set promiscuous mode for a GbE interface */
+native_t
+unm_niu_set_promiscuous_mode(struct unm_adapter_s *adapter,
+ unm_niu_prom_mode_t mode)
+{
+ native_t port = adapter->physical_port;
+ unm_niu_gb_drop_crc_t reg;
+ unm_niu_gb_mac_config_0_t mac_cfg;
+ unm_crbword_t data;
+ int cnt = 0, ret = 0;
+ ulong_t val;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
+ return (-1);
+
+ /* Turn off mac */
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg, 4);
+ mac_cfg.rx_enable = 0;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg, 4);
+
+ /* wait until mac is drained by sre */
+ /* Port 0 rx fifo bit 5 */
+ val = (0x20 << port);
+ adapter->unm_crb_writelit_adapter(adapter, UNM_NIU_FRAME_COUNT_SELECT,
+ val);
+
+ do {
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_FRAME_COUNT,
+ &val, 4);
+ cnt++;
+ if (cnt > 2000) {
+ ret = -1;
+ break;
+ }
+ drv_usecwait(10);
+ } while (val);
+
+ /* now set promiscuous mode */
+ if (ret != -1) {
+ if (mode == UNM_NIU_PROMISCOUS_MODE)
+ data = 0;
+ else
+ data = 1;
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
+ &reg, 4);
+ switch (port) {
+ case 0:
+ reg.drop_gb0 = data;
+ break;
+ case 1:
+ reg.drop_gb1 = data;
+ break;
+ case 2:
+ reg.drop_gb2 = data;
+ break;
+ case 3:
+ reg.drop_gb3 = data;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
+ &reg, 4);
+ }
+
+ /* turn the mac on back */
+ mac_cfg.rx_enable = 1;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
+ &mac_cfg, 4);
+
+ return (ret);
+}
+
+/*
+ * Set the MAC address for an XG port
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+unm_niu_xg_macaddr_set(struct unm_adapter_s *adapter,
+ unm_ethernet_macaddr_t addr)
+{
+ int phy = adapter->physical_port;
+ unm_crbword_t temp = 0;
+ u32 port_mode = 0;
+
+ if ((phy < 0) || (phy > 3))
+ return (-1);
+
+ switch (phy) {
+ case 0:
+ (void) memcpy(&temp, addr, 2);
+ temp <<= 16;
+ port_mode = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_PORT_MODE_ADDR);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
+ temp = 0;
+ (void) memcpy(&temp, ((__uint8_t *)addr) + 2,
+ sizeof (unm_crbword_t));
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
+ } else {
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
+ temp = 0;
+ (void) memcpy(&temp, ((__uint8_t *)addr) + 2,
+ sizeof (unm_crbword_t));
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
+ }
+ break;
+
+ case 1:
+ (void) memcpy(&temp, addr, 2);
+ temp <<= 16;
+ port_mode = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_PORT_MODE_ADDR);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
+ temp = 0;
+ (void) memcpy(&temp, ((__uint8_t *)addr) + 2,
+ sizeof (unm_crbword_t));
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
+ } else {
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
+ temp = 0;
+ (void) memcpy(&temp, ((__uint8_t *)addr) + 2,
+ sizeof (unm_crbword_t));
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
+ }
+ break;
+
+ default:
+ cmn_err(CE_WARN, "Unknown port %d\n", phy);
+ return (DDI_FAILURE);
+ }
+
+ return (0);
+}
+
+native_t
+unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s *adapter,
+ unm_niu_prom_mode_t mode)
+{
+ long reg;
+ unm_niu_xg_mac_config_0_t mac_cfg;
+ native_t port = adapter->physical_port;
+ int cnt = 0;
+ int result = 0;
+ u32 port_mode = 0;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
+ return (-1);
+
+ port_mode = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_PORT_MODE_ADDR);
+
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ reg = 0;
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_NIU_GB_DROP_WRONGADDR, (void*)&reg, 4);
+ } else {
+ /* Turn off mac */
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
+ (0x10000 * port), &mac_cfg, 4);
+ mac_cfg.rx_enable = 0;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
+ (0x10000 * port), &mac_cfg, 4);
+
+ /* wait until mac is drained by sre */
+ if ((adapter->ahw.boardcfg.board_type !=
+ UNM_BRDTYPE_P2_SB31_10G_IMEZ) &&
+ (adapter->ahw.boardcfg.board_type !=
+ UNM_BRDTYPE_P2_SB31_10G_HMEZ)) {
+ /* single port case bit 9 */
+ reg = 0x0200;
+ adapter->unm_crb_writelit_adapter(adapter,
+ UNM_NIU_FRAME_COUNT_SELECT, reg);
+ } else {
+ /* Port 0 rx fifo bit 5 */
+ reg = (0x20 << port);
+ adapter->unm_crb_writelit_adapter(adapter,
+ UNM_NIU_FRAME_COUNT_SELECT, reg);
+ }
+ do {
+ adapter->unm_nic_hw_read_wx(adapter,
+ UNM_NIU_FRAME_COUNT, &reg, 4);
+ cnt++;
+ if (cnt > 2000) {
+ result = -1;
+ break;
+ }
+ drv_usecwait(10);
+ } while (reg);
+
+ /* now set promiscuous mode */
+ if (result != -1) {
+ adapter->unm_nic_hw_read_wx(adapter,
+ UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4);
+ if (mode == UNM_NIU_PROMISCOUS_MODE) {
+ reg = (reg | 0x2000UL);
+ } else { /* FIXME use the correct mode value here */
+ reg = (reg & ~0x2000UL);
+ }
+ adapter->unm_crb_writelit_adapter(adapter,
+ UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
+ }
+
+ /* turn the mac back on */
+ mac_cfg.rx_enable = 1;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
+ (0x10000 * port), &mac_cfg, 4);
+ }
+
+ return (result);
+}
+
+int
+unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
+{
+ int port = adapter->physical_port;
+ unm_niu_xg_pause_ctl_t reg;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
+ return (-1);
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
+ if (port == 0)
+ reg.xg0_mask = !enable;
+ else
+ reg.xg1_mask = !enable;
+
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
+
+ return (0);
+}
+
+int
+unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
+{
+ int port = adapter->physical_port;
+ unm_niu_gb_pause_ctl_t reg;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
+ return (-1);
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
+ switch (port) {
+ case (0):
+ reg.gb0_mask = !enable;
+ break;
+ case (1):
+ reg.gb1_mask = !enable;
+ break;
+ case (2):
+ reg.gb2_mask = !enable;
+ break;
+ case (3):
+ default:
+ reg.gb3_mask = !enable;
+ break;
+ }
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
+
+ return (0);
+}
+
+int
+unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s *adapter, int enable)
+{
+ int port = adapter->physical_port;
+ unm_niu_gb_mac_config_0_t reg;
+
+ if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
+ return (-1);
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
+ &reg, 4);
+ reg.rx_flowctl = enable;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
+ &reg, 4);
+
+ return (0);
+}
diff --git a/usr/src/uts/common/io/ntxn/nx_errorcode.h b/usr/src/uts/common/io/ntxn/nx_errorcode.h
new file mode 100644
index 0000000000..9a14578900
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/nx_errorcode.h
@@ -0,0 +1,81 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Error codes for HAL - NIC interface.
+ *
+ */
+
+#ifndef _NX_ERRORCODE_H_
+#define _NX_ERRORCODE_H_
+
+/*
+ * Common Error Codes
+ */
+
+#define NX_RCODE_SUCCESS 0
+/* Insuff. mem resource on host */
+#define NX_RCODE_NO_HOST_MEM 1
+/* Insuff. misc. resources on host */
+#define NX_RCODE_NO_HOST_RESOURCE 2
+/* Insuff. crb resources on card */
+#define NX_RCODE_NO_CARD_CRB 3
+/* Insuff. mem resources on card */
+#define NX_RCODE_NO_CARD_MEM 4
+/* Insuff. misc. resources on card */
+#define NX_RCODE_NO_CARD_RESOURCE 5
+/* One or more args to routine were out-of-range */
+#define NX_RCODE_INVALID_ARGS 6
+/* Requested action is invalid / in error */
+#define NX_RCODE_INVALID_ACTION 7
+/* Requested RX/TX has invalid state */
+#define NX_RCODE_INVALID_STATE 8
+/* Requested action is not supported */
+#define NX_RCODE_NOT_SUPPORTED 9
+/* Requested action is not allowed */
+#define NX_RCODE_NOT_PERMITTED 10
+/* System not ready for action */
+#define NX_RCODE_NOT_READY 11
+/* Target of requested action does not exist */
+#define NX_RCODE_DOES_NOT_EXIST 2
+/* Requested action already performed/complete */
+#define NX_RCODE_ALREADY_EXISTSi 13
+/* Invalid signature provided */
+#define NX_RCODE_BAD_SIGNATURE 14
+/* Valid command, not implemented */
+#define NX_RCODE_CMD_NOT_IMPLi 15
+/* Invalid/Unknown command */
+#define NX_RCODE_CMD_INVALID 16
+/* Timeout on polling rsp status */
+#define NX_RCODE_TIMEOUT 17
+#define NX_RCODE_CMD_FAILED 18
+#define NX_RCODE_MAX_EXCEEDED 19
+#define NX_RCODE_MAX 20
+
+/*
+ * Macros
+ */
+#define NX_IS_RCODE_VALID(ERR) (ERR >= NX_RCODE_MAX)
+
+#endif /* _NX_ERRORCODE_H_ */
diff --git a/usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h b/usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h
new file mode 100644
index 0000000000..9577d4b3e1
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h
@@ -0,0 +1,168 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __NX_HW_REGS_H
+#define __NX_HW_REGS_H
+
+/*
+ * PCI related defines.
+ */
+
+/*
+ * Interrupt related defines.
+ */
+#define PCIX_TARGET_STATUS (0x10118)
+#define PCIX_TARGET_STATUS_F1 (0x10160)
+#define PCIX_TARGET_STATUS_F2 (0x10164)
+#define PCIX_TARGET_STATUS_F3 (0x10168)
+#define PCIX_TARGET_STATUS_F4 (0x10360)
+#define PCIX_TARGET_STATUS_F5 (0x10364)
+#define PCIX_TARGET_STATUS_F6 (0x10368)
+#define PCIX_TARGET_STATUS_F7 (0x1036c)
+
+#define PCIX_TARGET_MASK (0x10128)
+#define PCIX_TARGET_MASK_F1 (0x10170)
+#define PCIX_TARGET_MASK_F2 (0x10174)
+#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F4 (0x10370)
+#define PCIX_TARGET_MASK_F5 (0x10374)
+#define PCIX_TARGET_MASK_F6 (0x10378)
+#define PCIX_TARGET_MASK_F7 (0x1037c)
+
+/*
+ * Message Signaled Interrupts
+ */
+#define PCIX_MSI_F0 (0x13000)
+#define PCIX_MSI_F1 (0x13004)
+#define PCIX_MSI_F2 (0x13008)
+#define PCIX_MSI_F3 (0x1300c)
+#define PCIX_MSI_F4 (0x13010)
+#define PCIX_MSI_F5 (0x13014)
+#define PCIX_MSI_F6 (0x13018)
+#define PCIX_MSI_F7 (0x1301c)
+#define PCIX_MSI_F(FUNC) (0x13000 +((FUNC) * 4))
+
+/*
+ *
+ */
+#define PCIX_INT_VECTOR (0x10100)
+#define PCIX_INT_MASK (0x10104)
+
+/*
+ * Interrupt state machine and other bits.
+ */
+#define PCIE_MISCCFG_RC (0x1206c)
+
+
+#define ISR_INT_TARGET_STATUS (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS))
+#define ISR_INT_TARGET_STATUS_F1 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F1))
+#define ISR_INT_TARGET_STATUS_F2 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F2))
+#define ISR_INT_TARGET_STATUS_F3 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
+#define ISR_INT_TARGET_STATUS_F4 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_STATUS_F5 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_STATUS_F6 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_STATUS_F7 (UNM_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+
+#define ISR_INT_TARGET_MASK (UNM_PCIX_PS_REG(PCIX_TARGET_MASK))
+#define ISR_INT_TARGET_MASK_F1 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F1))
+#define ISR_INT_TARGET_MASK_F2 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
+#define ISR_INT_TARGET_MASK_F3 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_MASK_F4 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_MASK_F5 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_MASK_F6 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_MASK_F7 (UNM_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
+
+#define ISR_INT_VECTOR (UNM_PCIX_PS_REG(PCIX_INT_VECTOR))
+#define ISR_INT_MASK (UNM_PCIX_PS_REG(PCIX_INT_MASK))
+#define ISR_INT_STATE_REG (UNM_PCIX_PS_REG(PCIE_MISCCFG_RC))
+
+#define ISR_MSI_INT_TRIGGER(FUNC) (UNM_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+
+#define ISR_IS_LEGACY_INTR_IDLE(VAL) (((VAL) & 0x300) == 0)
+#define ISR_IS_LEGACY_INTR_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define PCIX_INT_VECTOR_BIT_F0 0x0080
+#define PCIX_INT_VECTOR_BIT_F1 0x0100
+#define PCIX_INT_VECTOR_BIT_F2 0x0200
+#define PCIX_INT_VECTOR_BIT_F3 0x0400
+#define PCIX_INT_VECTOR_BIT_F4 0x0800
+#define PCIX_INT_VECTOR_BIT_F5 0x1000
+#define PCIX_INT_VECTOR_BIT_F6 0x2000
+#define PCIX_INT_VECTOR_BIT_F7 0x4000
+
+struct nx_legacy_intr_set {
+ __uint32_t int_vec_bit;
+ __uint32_t tgt_status_reg;
+ __uint32_t tgt_mask_reg;
+ __uint32_t pci_int_reg;
+};
+
+#define NX_LEGACY_INTR_CONFIG \
+{ \
+ { PCIX_INT_VECTOR_BIT_F0, \
+ ISR_INT_TARGET_STATUS, \
+ ISR_INT_TARGET_MASK, \
+ ISR_MSI_INT_TRIGGER(0) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F1, \
+ ISR_INT_TARGET_STATUS_F1, \
+ ISR_INT_TARGET_MASK_F1, \
+ ISR_MSI_INT_TRIGGER(1) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F2, \
+ ISR_INT_TARGET_STATUS_F2, \
+ ISR_INT_TARGET_MASK_F2, \
+ ISR_MSI_INT_TRIGGER(2) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F3, \
+ ISR_INT_TARGET_STATUS_F3, \
+ ISR_INT_TARGET_MASK_F3, \
+ ISR_MSI_INT_TRIGGER(3) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F4, \
+ ISR_INT_TARGET_STATUS_F4, \
+ ISR_INT_TARGET_MASK_F4, \
+ ISR_MSI_INT_TRIGGER(4) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F5, \
+ ISR_INT_TARGET_STATUS_F5, \
+ ISR_INT_TARGET_MASK_F5, \
+ ISR_MSI_INT_TRIGGER(5) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F6, \
+ ISR_INT_TARGET_STATUS_F6, \
+ ISR_INT_TARGET_MASK_F6, \
+ ISR_MSI_INT_TRIGGER(6) }, \
+ \
+ { PCIX_INT_VECTOR_BIT_F7, \
+ ISR_INT_TARGET_STATUS_F7, \
+ ISR_INT_TARGET_MASK_F7, \
+ ISR_MSI_INT_TRIGGER(7) }, \
+}
+
+#endif /* __NX_HW_REGS_H */
diff --git a/usr/src/uts/common/io/ntxn/nxhal_nic_interface.h b/usr/src/uts/common/io/ntxn/nxhal_nic_interface.h
new file mode 100644
index 0000000000..278474999b
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/nxhal_nic_interface.h
@@ -0,0 +1,545 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Data types and structure for HAL - NIC interface.
+ *
+ */
+
+#ifndef _NXHAL_NIC_INTERFACE_H_
+#define _NXHAL_NIC_INTERFACE_H_
+
+/*
+ * Simple Types
+ */
+
+typedef U32 nx_reg_addr_t;
+
+/*
+ * Root crb-based firmware commands
+ */
+
+/*
+ * CRB Root Command
+ * A single set of crbs is used across all physical/virtual
+ * functions for capability queries, initialization, and
+ * context creation/destruction.
+ *
+ * There are 4 CRBS:
+ * Command/Response CRB
+ * Argument1 CRB
+ * Argument2 CRB
+ * Argument3 CRB
+ * Signature CRB
+ *
+ * The cmd/rsp crb is always intiated by the host via
+ * a command code and always responded by the card with
+ * a response code. The cmd and rsp codes are disjoint.
+ * The sequence of use is always CMD, RSP, CLEAR CMD.
+ *
+ * The arguments are for passing in command specific
+ * and response specific parameters/data.
+ *
+ * The signature is composed of a magic value, the
+ * pci function id, and a command sequence id:
+ * [7:0] = pci function
+ * [15:8] = version
+ * [31:16] = magic of 0xcafe
+ *
+ * The pci function allows the card to take correct
+ * action for the given particular commands.
+ * The firmware will attempt to detect
+ * an errant driver that has died while holding
+ * the root crb hardware lock. Such an error condition
+ * shows up as the cmd/rsp crb stuck in a non-clear state.
+ *
+ * Interface Sequence:
+ * Host always makes requests and firmware always responds.
+ * Note that data field is always set prior to command field.
+ *
+ * [READ] CMD/RSP CRB ARGUMENT FIELD
+ * Host grab lock
+ * Host -> CMD optional parameter
+ * FW <- (Good) RSP-OK DATA
+ * FW <- (Fail) RSP-FAIL optional failure code
+ * Host -> CLEAR
+ * Host release lock
+ *
+ * [WRITE] CMD/RSP CRB ARGUMENT FIELD
+ * Host grab lock
+ * Host -> CMD DATA
+ * FW <- (Good) RSP-OK optional write status
+ * FW <- (Write) RSP-FAIL optional failure code
+ * Host -> CLEAR
+ * Host release lock
+ */
+
+
+/*
+ * CMD/RSP
+ */
+
+#define NX_CDRP_SIGNATURE_TO_PCIFN(sign) ((sign) & 0xff)
+#define NX_CDRP_SIGNATURE_TO_VERSION(sign) (((sign)>>8) & 0xff)
+#define NX_CDRP_SIGNATURE_TO_MAGIC(sign) (((sign)>>16) & 0xffff)
+#define NX_CDRP_SIGNATURE_VALID(sign) \
+ (NX_CDRP_SIGNATURE_TO_MAGIC(sign) == 0xcafe && \
+ NX_CDRP_SIGNATURE_TO_PCIFN(sign) < 8)
+#define NX_CDRP_SIGNATURE_MAKE(pcifn, version) \
+ (((pcifn) & 0xff) | \
+ (((version) & 0xff) << 8) | \
+ ((u32)0xcafe << 16))
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ * The macros below do not have it explicitly set to
+ * allow their use in lookup tables
+ */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+/* [CMD] Capability Vector [RSP] Capability Vector */
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+
+/* [CMD] - [RSP] Query Value */
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+
+/* [CMD] Rx Config DMA Addr [RSP] rcode */
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+
+/* [CMD] Rx Context Handle, Reset Kind [RSP] rcode */
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+
+/* [CMD] Tx Config DMA Addr [RSP] rcode */
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+
+/* [CMD] Tx Context Handle, Reset Kind [RSP] rcode */
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+
+/* [CMD] Stat setup dma addr - [RSP] Handle, rcode */
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+
+/* [CMD] Handle - [RSP] rcode */
+#define NX_CDRP_CMD_GET_STATISTICS 0x0000000f
+
+/* [CMD] Handle - [RSP] rcode */
+#define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010
+
+/* [CMD] - [RSP] rcode */
+#define NX_CDRP_CMD_GEN_INT 0x00000011
+
+/* [CMD] MTU - [RSP] rcode */
+#define NX_CDRP_CMD_SET_MTU 0x00000012
+
+#define NX_CDRP_CMD_MAX 0x00000013
+
+/*
+ * Capabilities
+ */
+
+#define NX_CAP_BIT(class, bit) (1 << bit)
+
+/* Class 0 (i.e. ARGS 1) */
+#define NX_CAP0_LEGACY_CONTEXT NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO NX_CAP_BIT(0, 5)
+#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
+#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
+#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
+
+/* Class 1 (i.e. ARGS 2) */
+#define NX_CAP1_NIC NX_CAP_BIT(1, 0)
+#define NX_CAP1_PXE NX_CAP_BIT(1, 1)
+#define NX_CAP1_CHIMNEY NX_CAP_BIT(1, 2)
+#define NX_CAP1_LSA NX_CAP_BIT(1, 3)
+#define NX_CAP1_RDMA NX_CAP_BIT(1, 4)
+#define NX_CAP1_ISCSI NX_CAP_BIT(1, 5)
+#define NX_CAP1_FCOE NX_CAP_BIT(1, 6)
+
+/* Class 2 (i.e. ARGS 3) */
+
+/*
+ * Rules
+ */
+
+typedef U32 nx_rx_rule_type_t;
+
+#define NX_RX_RULETYPE_DEFAULT 0
+#define NX_RX_RULETYPE_MAC 1
+#define NX_RX_RULETYPE_MAC_VLAN 2
+#define NX_RX_RULETYPE_MAC_RSS 3
+#define NX_RX_RULETYPE_MAC_VLAN_RSS 4
+#define NX_RX_RULETYPE_MAX 5
+
+typedef U32 nx_rx_rule_cmd_t;
+
+#define NX_RX_RULECMD_ADD 0
+#define NX_RX_RULECMD_REMOVE 1
+#define NX_RX_RULECMD_MAX 2
+
+typedef struct nx_rx_rule_arg_s {
+ union {
+ struct {
+ char mac[6];
+ } m;
+ struct {
+ char mac[6];
+ char vlan;
+ } mv;
+ struct {
+ char mac[6];
+ } mr;
+ struct {
+ char mac[6];
+ char vlan;
+ } mvr;
+ } s1;
+ /* will be union of all the different args for rules */
+ U64 data;
+} nx_rx_rule_arg_t;
+
+typedef struct nx_rx_rule_s {
+ U32 id;
+ U32 active;
+ nx_rx_rule_arg_t arg;
+ nx_rx_rule_type_t type;
+} nx_rx_rule_t;
+
+/* MSG - REQUIRES TX CONTEXT */
+
+/*
+ * The rules can be added/deleted from both the
+ * host and card sides so rq/rsp are similar.
+ */
+typedef struct nx_hostmsg_rx_rule_s {
+ nx_rx_rule_cmd_t cmd;
+ nx_rx_rule_t rule;
+} nx_hostmsg_rx_rule_t;
+
+typedef struct nx_cardmsg_rx_rule_s {
+ nx_rcode_t rcode;
+ nx_rx_rule_cmd_t cmd;
+ nx_rx_rule_t rule;
+} nx_cardmsg_rx_rule_t;
+
+
+/*
+ * Common to Rx/Tx contexts
+ */
+
+/*
+ * Context states
+ */
+
+typedef U32 nx_host_ctx_state_t;
+
+#define NX_HOST_CTX_STATE_FREED 0 /* Invalid state */
+#define NX_HOST_CTX_STATE_ALLOCATED 1 /* Not committed */
+/* The following states imply FW is aware of context */
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+/*
+ * Interrupt mask crb use must be set identically on the Tx
+ * and Rx context configs across a pci function
+ */
+
+/* Rx and Tx have unique interrupt/crb */
+#define NX_HOST_INT_CRB_MODE_UNIQUE 0
+/* Rx and Tx share a common interrupt/crb */
+#define NX_HOST_INT_CRB_MODE_SHARED 1 /* <= LEGACY */
+/* Rx does not use a crb */
+#define NX_HOST_INT_CRB_MODE_NORX 2
+/* Tx does not use a crb */
+#define NX_HOST_INT_CRB_MODE_NOTX 3
+/* Neither Rx nor Tx use a crb */
+#define NX_HOST_INT_CRB_MODE_NORXTX 4
+
+/*
+ * Destroy Rx/Tx
+ */
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+
+/*
+ * Tx
+ */
+
+/*
+ * Components of the host-request for Tx context creation.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_cds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U32 ring_size; /* Ring entries */
+ U32 rsvd; /* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct nx_hostrq_tx_ctx_s {
+ U64 host_rsp_dma_addr; /* Response dma'd here */
+ U64 cmd_cons_dma_addr; /* */
+ U64 dummy_dma_addr; /* */
+ U32 capabilities[4]; /* Flag bit vector */
+ U32 host_int_crb_mode; /* Interrupt crb usage */
+ U32 rsvd1; /* Padding */
+ U16 rsvd2; /* Padding */
+ U16 interrupt_ctl;
+ U16 msi_index;
+ U16 rsvd3; /* Padding */
+ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
+ U8 reserved[128]; /* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct nx_cardrsp_cds_ring_s {
+ U32 host_producer_crb; /* Crb to use */
+ U32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct nx_cardrsp_tx_ctx_s {
+ U32 host_ctx_state; /* Starting state */
+ U16 context_id; /* Handle for context */
+ U8 phys_port; /* Physical id of port */
+ U8 virt_port; /* Virtual/Logical id of port */
+ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
+ U8 reserved[128]; /* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) \
+ (sizeof (HOSTRQ_TX))
+
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX) \
+ (sizeof (CARDRSP_TX))
+
+/*
+ * Rx
+ */
+
+/*
+ * RDS ring mapping to producer crbs
+ */
+
+/* Each ring has a unique crb */
+#define NX_HOST_RDS_CRB_MODE_UNIQUE 0 /* <= LEGACY */
+
+/*
+ * All configured RDS Rings share common crb:
+ * 1 Ring - same as unique
+ * 2 Rings - 16, 16
+ * 3 Rings - 10, 10, 10
+ */
+#define NX_HOST_RDS_CRB_MODE_SHARED 1
+
+/*
+ * Bit usage is specified per-ring using the
+ * ring's size. Sum of bit lengths must be <= 32.
+ * Packing is [Ring N] ... [Ring 1][Ring 0]
+ */
+#define NX_HOST_RDS_CRB_MODE_CUSTOM 2
+#define NX_HOST_RDS_CRB_MODE_MAX 3
+
+
+/*
+ * RDS Ting Types
+ */
+
+#define NX_RDS_RING_TYPE_NORMAL 0
+#define NX_RDS_RING_TYPE_JUMBO 1
+#define NX_RDS_RING_TYPE_LRO 2
+#define NX_RDS_RING_TYPE_MAX 3
+
+/*
+ * Components of the host-request for Rx context creation.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_sds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U32 ring_size; /* Ring entries */
+ U16 msi_index;
+ U16 rsvd; /* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct nx_hostrq_rds_ring_s {
+ U64 host_phys_addr; /* Ring base addr */
+ U64 buff_size; /* Packet buffer size */
+ U32 ring_size; /* Ring entries */
+ U32 ring_kind; /* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct nx_hostrq_rx_ctx_s {
+ U64 host_rsp_dma_addr; /* Response dma'd here */
+ U32 capabilities[4]; /* Flag bit vector */
+ U32 host_int_crb_mode; /* Interrupt crb usage */
+ U32 host_rds_crb_mode; /* RDS crb usage */
+ /* These ring offsets are relative to data[0] below */
+ U32 rds_ring_offset; /* Offset to RDS config */
+ U32 sds_ring_offset; /* Offset to SDS config */
+ U16 num_rds_rings; /* Count of RDS rings */
+ U16 num_sds_rings; /* Count of SDS rings */
+ U16 rsvd1; /* Padding */
+ U16 rsvd2; /* Padding */
+ U8 reserved[128]; /* reserve space for future expansion */
+ /*
+ * MUST BE 64-bit aligned.
+ * The following is packed:
+ * - N hostrq_rds_rings
+ * - N hostrq_sds_rings
+ */
+ char data[];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct nx_cardrsp_rds_ring_s {
+ U32 host_producer_crb; /* Crb to use */
+ U32 rsvd1; /* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct nx_cardrsp_sds_ring_s {
+ U32 host_consumer_crb; /* Crb to use */
+ U32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct nx_cardrsp_rx_ctx_s {
+ /* These ring offsets are relative to data[0] below */
+ U32 rds_ring_offset; /* Offset to RDS config */
+ U32 sds_ring_offset; /* Offset to SDS config */
+ U32 host_ctx_state; /* Starting State */
+ U32 num_fn_per_port; /* How many PCI fn share the port */
+ U16 num_rds_rings; /* Count of RDS rings */
+ U16 num_sds_rings; /* Count of SDS rings */
+ U16 context_id; /* Handle for context */
+ U8 phys_port; /* Physical id of port */
+ U8 virt_port; /* Virtual/Logical id of port */
+ U8 reserved[128]; /* save space for future expansion */
+ /*
+ * MUST BE 64-bit aligned.
+ * The following is packed:
+ * - N cardrsp_rds_rings
+ * - N cardrs_sds_rings
+ */
+ char data[];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \
+ (sizeof (HOSTRQ_RX) + \
+ (rds_rings)*(sizeof (nx_hostrq_rds_ring_t)) + \
+ (sds_rings)*(sizeof (nx_hostrq_sds_ring_t)))
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \
+ (sizeof (CARDRSP_RX) + \
+ (rds_rings)*(sizeof (nx_cardrsp_rds_ring_t)) + \
+ (sds_rings)*(sizeof (nx_cardrsp_sds_ring_t)))
+
+
+/*
+ * Statistics
+ */
+
+/*
+ * The model of statistics update to use
+ */
+
+#define NX_STATISTICS_MODE_INVALID 0
+
+/*
+ * Permanent setup; Updates are only sent on explicit request
+ * NX_CDRP_CMD_GET_STATISTICS)
+ */
+#define NX_STATISTICS_MODE_PULL 1
+
+/*
+ * Permanent setup; Updates are sent automatically and on
+ * explicit request (NX_CDRP_CMD_GET_STATISTICS)
+ */
+#define NX_STATISTICS_MODE_PUSH 2
+
+/* One time stat update. */
+#define NX_STATISTICS_MODE_SINGLE_SHOT 3
+
+#define NX_STATISTICS_MODE_MAX 4
+
+/*
+ * What set of stats
+ */
+#define NX_STATISTICS_TYPE_INVALID 0
+#define NX_STATISTICS_TYPE_NIC_RX_CORE 1
+#define NX_STATISTICS_TYPE_NIC_TX_CORE 2
+#define NX_STATISTICS_TYPE_NIC_RX_ALL 3
+#define NX_STATISTICS_TYPE_NIC_TX_ALL 4
+#define NX_STATISTICS_TYPE_MAX 5
+
+
+/*
+ * Request to setup statistics gathering.
+ * CRB - DOES NOT REQUIRE Rx/TX CONTEXT
+ */
+
+typedef struct nx_hostrq_stat_setup_s {
+ U64 host_stat_buffer; /* Where to dma stats */
+ U32 host_stat_size; /* Size of stat buffer */
+ U16 context_id; /* Which context */
+ U16 stat_type; /* What class of stats */
+ U16 stat_mode; /* When to update */
+ U16 stat_interval; /* Frequency of update */
+} nx_hostrq_stat_setup_t;
+
+
+
+#endif /* _NXHAL_NIC_INTERFACE_H_ */
diff --git a/usr/src/uts/common/io/ntxn/unm_brdcfg.h b/usr/src/uts/common/io/ntxn/unm_brdcfg.h
new file mode 100644
index 0000000000..8ede594d5d
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_brdcfg.h
@@ -0,0 +1,273 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __UNM_BRDINFO_H
+#define __UNM_BRDINFO_H
+
+/* The version of the main data structure */
+#define UNM_BDINFO_VERSION 1
+
+/* Magic number to let user know flash is programmed */
+#define UNM_BDINFO_MAGIC 0x12345678
+
+#define P2_CHIP 2
+#define P3_CHIP 3
+#define NX_P2_C0 0x24
+#define NX_P2_C1 0x25
+#define NX_P3_A0 0x30
+#define NX_P3_A2 0x32
+#define NX_P3_B0 0x40
+#define NX_P3_B1 0x41
+#define NX_P3_B2 0x42
+
+#define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1)
+#define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0)
+
+typedef enum {
+ UNM_BRDTYPE_P1_BD = 0x0000,
+ UNM_BRDTYPE_P1_SB = 0x0001,
+ UNM_BRDTYPE_P1_SMAX = 0x0002,
+ UNM_BRDTYPE_P1_SOCK = 0x0003,
+
+ UNM_BRDTYPE_P2_SOCK_31 = 0x0008,
+ UNM_BRDTYPE_P2_SOCK_35 = 0x0009,
+ UNM_BRDTYPE_P2_SB35_4G = 0x000a,
+ UNM_BRDTYPE_P2_SB31_10G = 0x000b,
+ UNM_BRDTYPE_P2_SB31_2G = 0x000c,
+
+ UNM_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
+ UNM_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
+ UNM_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
+
+ /* Reference quad gig */
+ UNM_BRDTYPE_P3_REF_QG = 0x0021,
+ UNM_BRDTYPE_P3_HMEZ = 0x0022,
+ /* Dual CX4 - Low Profile - Red card */
+ UNM_BRDTYPE_P3_10G_CX4_LP = 0x0023,
+ UNM_BRDTYPE_P3_4_GB = 0x0024,
+ UNM_BRDTYPE_P3_IMEZ = 0x0025,
+ UNM_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
+ UNM_BRDTYPE_P3_10000_BASE_T = 0x0027,
+ UNM_BRDTYPE_P3_XG_LOM = 0x0028,
+
+ UNM_BRDTYPE_P3_4_GB_MM = 0x0029,
+ UNM_BRDTYPE_P3_10G_CX4 = 0x0031, /* Reference CX4 */
+ UNM_BRDTYPE_P3_10G_XFP = 0x0032, /* Reference XFP */
+
+ UNM_BRDTYPE_P3_10G_TRP = 0x0080,
+
+} unm_brdtype_t;
+
+typedef enum {
+ NX_UNKNOWN_TYPE_ROMIMAGE = 0,
+ NX_P2_MN_TYPE_ROMIMAGE = 1,
+ NX_P3_CT_TYPE_ROMIMAGE,
+ NX_P3_MN_TYPE_ROMIMAGE,
+ NX_P3_MS_TYPE_ROMIMAGE,
+ NX_UNKNOWN_TYPE_ROMIMAGE_LAST,
+} nx_fw_type_t;
+
+/* board type specific information */
+typedef struct {
+ unm_brdtype_t brdtype; /* type of board */
+ long ports; /* max no of physical ports */
+ nx_fw_type_t fwtype; /* The FW Associated with board type */
+ char *short_name;
+} unm_brdinfo_t;
+
+#define NUM_SUPPORTED_BOARDS (sizeof (unm_boards)/sizeof (unm_brdinfo_t))
+
+#define GET_BRD_NAME_BY_TYPE(type, name) \
+{ \
+ int i, found = 0; \
+ for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { \
+ if (unm_boards[i].brdtype == type) { \
+ name = unm_boards[i].short_name; \
+ found = 1; \
+ break; \
+ } \
+ } \
+ if (!found) \
+ name = "Unknown"; \
+}
+
+typedef struct {
+ __uint32_t header_version;
+
+ __uint32_t board_mfg;
+ __uint32_t board_type;
+ __uint32_t board_num;
+ __uint32_t chip_id;
+ __uint32_t chip_minor;
+ __uint32_t chip_major;
+ __uint32_t chip_pkg;
+ __uint32_t chip_lot;
+
+
+ __uint32_t port_mask; /* available niu ports */
+ __uint32_t peg_mask; /* available pegs */
+ __uint32_t icache_ok; /* can we run with icache? */
+ __uint32_t dcache_ok; /* can we run with dcache? */
+ __uint32_t casper_ok;
+
+ /* unm_eth_addr_t mac_address[MAX_PORTS]; */
+ __uint32_t mac_addr_lo_0;
+ __uint32_t mac_addr_lo_1;
+ __uint32_t mac_addr_lo_2;
+ __uint32_t mac_addr_lo_3;
+
+ /* MN-related config */
+ __uint32_t mn_sync_mode; /* enable/ sync shift cclk/ sync shift mclk */
+ __uint32_t mn_sync_shift_cclk;
+ __uint32_t mn_sync_shift_mclk;
+ __uint32_t mn_wb_en;
+ __uint32_t mn_crystal_freq; /* in MHz */
+ __uint32_t mn_speed; /* in MHz */
+ __uint32_t mn_org;
+ __uint32_t mn_depth;
+ __uint32_t mn_ranks_0; /* ranks per slot */
+ __uint32_t mn_ranks_1; /* ranks per slot */
+ __uint32_t mn_rd_latency_0;
+ __uint32_t mn_rd_latency_1;
+ __uint32_t mn_rd_latency_2;
+ __uint32_t mn_rd_latency_3;
+ __uint32_t mn_rd_latency_4;
+ __uint32_t mn_rd_latency_5;
+ __uint32_t mn_rd_latency_6;
+ __uint32_t mn_rd_latency_7;
+ __uint32_t mn_rd_latency_8;
+ __uint32_t mn_dll_val[18];
+ __uint32_t mn_mode_reg; /* See MIU DDR Mode Register */
+ __uint32_t mn_ext_mode_reg; /* See MIU DDR Extended Mode Register */
+ __uint32_t mn_timing_0; /* See MIU Memory Control Timing Rgister */
+ __uint32_t mn_timing_1; /* See MIU Extended Memory Ctrl Timing Register */
+ __uint32_t mn_timing_2; /* See MIU Extended Memory Ctrl Timing2 Register */
+
+ /* SN-related config */
+ __uint32_t sn_sync_mode; /* enable/ sync shift cclk / sync shift mclk */
+ __uint32_t sn_pt_mode; /* pass through mode */
+ __uint32_t sn_ecc_en;
+ __uint32_t sn_wb_en;
+ __uint32_t sn_crystal_freq;
+ __uint32_t sn_speed;
+ __uint32_t sn_org;
+ __uint32_t sn_depth;
+ __uint32_t sn_dll_tap;
+ __uint32_t sn_rd_latency;
+
+ __uint32_t mac_addr_hi_0;
+ __uint32_t mac_addr_hi_1;
+ __uint32_t mac_addr_hi_2;
+ __uint32_t mac_addr_hi_3;
+
+ __uint32_t magic; /* indicates flash has been initialized */
+
+ __uint32_t mn_rdimm;
+ __uint32_t mn_dll_override;
+ __uint32_t coreclock_speed;
+} unm_board_info_t;
+
+#define FLASH_NUM_PORTS 4
+
+typedef struct {
+ __uint32_t flash_addr[32];
+} unm_flash_mac_addr_t;
+
+/* flash user area */
+typedef struct {
+ __uint8_t flash_md5[16];
+ __uint8_t crbinit_md5[16];
+ __uint8_t brdcfg_md5[16];
+ /* bootloader */
+ __uint32_t bootld_version;
+ __uint32_t bootld_size;
+ __uint8_t bootld_md5[16];
+ /* image */
+ __uint32_t image_version;
+ __uint32_t image_size;
+ __uint8_t image_md5[16];
+ /* primary image status */
+ __uint32_t primary_status;
+ __uint32_t secondary_present;
+
+ /* MAC address , 4 ports */
+ unm_flash_mac_addr_t mac_addr[FLASH_NUM_PORTS];
+
+ /* Any user defined data */
+} unm_old_user_info_t;
+
+#define FLASH_NUM_MAC_PER_PORT 32
+typedef struct {
+ __uint8_t flash_md5[16 * 64];
+ // __uint8_t crbinit_md5[16];
+ // __uint8_t brdcfg_md5[16];
+ /* bootloader */
+ __uint32_t bootld_version;
+ __uint32_t bootld_size;
+ // __uint8_t bootld_md5[16];
+ /* image */
+ __uint32_t image_version;
+ __uint32_t image_size;
+ // U8 image_md5[16];
+ /* primary image status */
+ __uint32_t primary_status;
+ __uint32_t secondary_present;
+
+ /* MAC address , 4 ports, 32 address per port */
+ __uint64_t mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
+ __uint32_t sub_sys_id;
+ __uint8_t serial_num[32];
+ __uint32_t bios_version;
+ __uint32_t pxe_enable; /* bitmask, per port */
+ __uint32_t vlan_tag[FLASH_NUM_PORTS];
+
+ /* Any user defined data */
+} unm_user_info_t;
+
+/* Flash memory map */
+typedef enum {
+ CRBINIT_START = 0, /* Crbinit section */
+ BRDCFG_START = 0x4000, /* board config */
+ INITCODE_START = 0x6000, /* pegtune code */
+ BOOTLD_START = 0x10000, /* bootld */
+ BOOTLD1_START = 0x14000, /* Start of booloader 1 */
+ IMAGE_START = 0x43000, /* compressed image */
+ SECONDARY_START = 0x200000, /* backup images */
+ PXE_FIRST_STAGE_INTEL = 0x3C0000, /* Intel First Stage info */
+ PXE_FIRST_STAGE_PPC = 0x3C4000, /* PPC First Stage info */
+ PXE_SECOND_STAGE_INTEL = 0x3B0000, /* Intel Second Stage info */
+ PXE_SECOND_STAGE_PPC = 0x3A0000, /* Intel Second Stage info */
+// LICENSE_TIME_START = 0x3C0000, /* license expiry time info */
+ PXE_START = 0x3D0000, /* PXE image area */
+ DEFAULT_DATA_START = 0x3e0000, /* where we place default factory data */
+ /* User defined region for new boards */
+ USER_START = 0x3E8000,
+ VPD_START = 0x3E8C00, /* Vendor private data */
+ LICENSE_START = 0x3E9000, /* Firmware License */
+ FIXED_START = 0x3F0000 /* backup of crbinit */
+} unm_flash_map_t;
+
+#define USER_START_OLD PXE_START /* for backward compatibility */
+
+#endif /* !__UNM_BRDINFO_H */
diff --git a/usr/src/uts/common/io/ntxn/unm_gem.c b/usr/src/uts/common/io/ntxn/unm_gem.c
new file mode 100644
index 0000000000..7f7dd27aec
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_gem.c
@@ -0,0 +1,1489 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+#include <sys/pci.h>
+#include <sys/ddi_intr.h>
+
+#include "unm_nic.h"
+#include "unm_nic_hw.h"
+#include "unm_brdcfg.h"
+#include "nic_cmn.h"
+#include "nic_phan_reg.h"
+#include "unm_nic_ioctl.h"
+#include "nx_hw_pci_regs.h"
+
+char ident[] = "Netxen nic driver v" UNM_NIC_VERSIONID;
+char unm_nic_driver_name[] = "ntxn";
+int verbmsg = 0;
+
+static char txbcopythreshold_propname[] = "tx_bcopy_threshold";
+static char rxbcopythreshold_propname[] = "rx_bcopy_threshold";
+static char rxringsize_propname[] = "rx_ring_size";
+static char jumborxringsize_propname[] = "jumbo_rx_ring_size";
+static char txringsize_propname[] = "tx_ring_size";
+static char defaultmtu_propname[] = "default_mtu";
+static char dmesg_propname[] = "verbose_driver";
+
+#define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a))
+
+extern int unm_register_mac(unm_adapter *adapter);
+extern void unm_fini_kstats(unm_adapter* adapter);
+extern void unm_nic_remove(unm_adapter *adapter);
+extern int unm_nic_suspend(unm_adapter *);
+extern uint_t unm_intr(caddr_t, caddr_t);
+
+/* Data access requirements. */
+static struct ddi_device_acc_attr unm_dev_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+static struct ddi_device_acc_attr unm_buf_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+static ddi_dma_attr_t unm_dma_attr_desc = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* dma_attr_addr_lo */
+ 0xffffffffull, /* dma_attr_addr_hi */
+ 0x000fffffull, /* dma_attr_count_max */
+ 4096, /* dma_attr_align */
+ 0x000fffffull, /* dma_attr_burstsizes */
+ 4, /* dma_attr_minxfer */
+ 0x003fffffull, /* dma_attr_maxxfer */
+ 0xffffffffull, /* dma_attr_seg */
+ 1, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0 /* dma_attr_flags */
+};
+
+static ddi_dma_attr_t unm_dma_attr_rxbuf = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* dma_attr_addr_lo */
+ 0x7ffffffffULL, /* dma_attr_addr_hi */
+ 0xffffull, /* dma_attr_count_max */
+ 4096, /* dma_attr_align */
+ 0xfff8ull, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ 0xffffffffull, /* dma_attr_maxxfer */
+ 0xffffull, /* dma_attr_seg */
+ 1, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0 /* dma_attr_flags */
+};
+
+static ddi_dma_attr_t unm_dma_attr_cmddesc = {
+ DMA_ATTR_V0, /* dma_attr_version */
+ 0, /* dma_attr_addr_lo */
+ 0x7ffffffffULL, /* dma_attr_addr_hi */
+ 0xffffull, /* dma_attr_count_max */
+ 1, /* dma_attr_align */
+ 0xfff8ull, /* dma_attr_burstsizes */
+ 1, /* dma_attr_minxfer */
+ 0xffff0ull, /* dma_attr_maxxfer */
+ 0xffffull, /* dma_attr_seg */
+ 16, /* dma_attr_sgllen */
+ 1, /* dma_attr_granular */
+ 0 /* dma_attr_flags */
+};
+
+static struct nx_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
+
+static int
+check_hw_init(struct unm_adapter_s *adapter)
+{
+ u32 val;
+ int ret = 0;
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_CAM_RAM(0x1fc), &val, 4);
+ if (val == 0x55555555) {
+ /* This is the first boot after power up */
+ adapter->unm_nic_hw_read_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
+ &val, 4);
+ if (val != 0x80000f)
+ ret = -1;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ /* Start P2 boot loader */
+ adapter->unm_nic_pci_write_normalize(adapter,
+ UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC);
+ adapter->unm_nic_pci_write_normalize(adapter,
+ UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+ }
+ return (ret);
+}
+
+
+static int
+unm_get_flash_block(unm_adapter *adapter, int base, int size, uint32_t *buf)
+{
+ int i, addr;
+ uint32_t *ptr32;
+
+ addr = base;
+ ptr32 = buf;
+ for (i = 0; i < size / sizeof (uint32_t); i++) {
+ if (rom_fast_read(adapter, addr, (int *)ptr32) == -1)
+ return (-1);
+ ptr32++;
+ addr += sizeof (uint32_t);
+ }
+ if ((char *)buf + size > (char *)ptr32) {
+ int local;
+
+ if (rom_fast_read(adapter, addr, &local) == -1)
+ return (-1);
+ (void) memcpy(ptr32, &local,
+ (uintptr_t)((char *)buf + size) - (uintptr_t)(char *)ptr32);
+ }
+
+ return (0);
+}
+
+
+static int
+get_flash_mac_addr(struct unm_adapter_s *adapter, u64 mac[])
+{
+ uint32_t *pmac = (uint32_t *)&mac[0];
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ uint32_t temp, crbaddr;
+ uint16_t *pmac16 = (uint16_t *)pmac;
+
+ // FOR P3, read from CAM RAM
+
+ int pci_func = adapter->ahw.pci_func;
+ pmac16 += (4*pci_func);
+ crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) +
+ (4 * (pci_func & 1));
+
+ adapter->unm_nic_hw_read_wx(adapter, crbaddr, &temp, 4);
+ if (pci_func & 1) {
+ *pmac16++ = (temp >> 16);
+ adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
+ &temp, 4);
+ *pmac16++ = (temp & 0xffff);
+ *pmac16++ = (temp >> 16);
+ *pmac16 = 0;
+ } else {
+ *pmac16++ = (temp & 0xffff);
+ *pmac16++ = (temp >> 16);
+ adapter->unm_nic_hw_read_wx(adapter, crbaddr+4,
+ &temp, 4);
+ *pmac16++ = (temp & 0xffff);
+ *pmac16 = 0;
+ }
+ return (0);
+ }
+
+
+ if (unm_get_flash_block(adapter, USER_START +
+ offsetof(unm_user_info_t, mac_addr), FLASH_NUM_PORTS * sizeof (U64),
+ pmac) == -1)
+ return (-1);
+
+ if (*mac == ~0ULL) {
+ if (unm_get_flash_block(adapter, USER_START_OLD +
+ offsetof(unm_old_user_info_t, mac_addr),
+ FLASH_NUM_PORTS * sizeof (U64), pmac) == -1)
+ return (-1);
+
+ if (*mac == ~0ULL)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+is_flash_supported(unm_adapter *adapter)
+{
+ int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
+ int addr, val01, val02, i, j;
+
+ /* if the flash size less than 4Mb, make huge war cry and die */
+ for (j = 1; j < 4; j++) {
+ addr = j * 0x100000;
+ for (i = 0; i < (sizeof (locs) / sizeof (locs[0])); i++) {
+ if (rom_fast_read(adapter, locs[i], &val01) == 0 &&
+ rom_fast_read(adapter, (addr + locs[i]),
+ &val02) == 0) {
+ if (val01 == val02)
+ return (-1);
+ } else {
+ return (-1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+unm_initialize_dummy_dma(unm_adapter *adapter)
+{
+ uint32_t hi, lo, temp;
+ ddi_dma_cookie_t cookie;
+
+ if (unm_pci_alloc_consistent(adapter, UNM_HOST_DUMMY_DMA_SIZE,
+ (caddr_t *)&adapter->dummy_dma.addr, &cookie,
+ &adapter->dummy_dma.dma_handle,
+ &adapter->dummy_dma.acc_handle) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: Unable to alloc dummy dma buf\n",
+ adapter->name, adapter->instance);
+ return (DDI_ENOMEM);
+ }
+
+ adapter->dummy_dma.phys_addr = cookie.dmac_laddress;
+
+ hi = (adapter->dummy_dma.phys_addr >> 32) & 0xffffffff;
+ lo = adapter->dummy_dma.phys_addr & 0xffffffff;
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI,
+ &hi, 4);
+ adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO,
+ &lo, 4);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ temp = DUMMY_BUF_INIT;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF,
+ &temp, 4);
+ }
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ return (DDI_SUCCESS);
+}
+
+void
+unm_free_dummy_dma(unm_adapter *adapter)
+{
+ if (adapter->dummy_dma.addr) {
+ unm_pci_free_consistent(&adapter->dummy_dma.dma_handle,
+ &adapter->dummy_dma.acc_handle);
+ adapter->dummy_dma.addr = NULL;
+ }
+}
+
+static int
+unm_pci_cfg_init(unm_adapter *adapter)
+{
+ hardware_context *hwcontext;
+ ddi_acc_handle_t pci_cfg_hdl;
+ int *reg_options;
+ dev_info_t *dip;
+ uint_t noptions;
+ int ret;
+ uint16_t vendor_id, pci_cmd_word;
+ uint8_t base_class, sub_class, prog_class;
+ uint32_t pexsizes;
+ struct nx_legacy_intr_set *legacy_intrp;
+
+ hwcontext = &adapter->ahw;
+ pci_cfg_hdl = adapter->pci_cfg_handle;
+ dip = adapter->dip;
+
+ vendor_id = pci_config_get16(pci_cfg_hdl, PCI_CONF_VENID);
+
+ if (vendor_id != 0x4040) {
+ cmn_err(CE_WARN, "%s%d: vendor id %x not 0x4040\n",
+ adapter->name, adapter->instance, vendor_id);
+ return (DDI_FAILURE);
+ }
+
+ ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
+ dip, 0, "reg", &reg_options, &noptions);
+ if (ret != DDI_PROP_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: Could not determine reg property\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ hwcontext->pci_func = (reg_options[0] >> 8) & 0x7;
+ ddi_prop_free(reg_options);
+
+ base_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_BASCLASS);
+ sub_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_SUBCLASS);
+ prog_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_PROGCLASS);
+
+ /*
+ * Need this check so that MEZZ card mgmt interface ntxn0 could fail
+ * attach & return and proceed to next interfaces ntxn1 and ntxn2
+ */
+ if ((base_class != 0x02) || (sub_class != 0) || (prog_class != 0)) {
+ cmn_err(CE_WARN, "%s%d: Base/sub/prog class problem %d/%d/%d\n",
+ adapter->name, adapter->instance, base_class, sub_class,
+ prog_class);
+ return (DDI_FAILURE);
+ }
+
+ hwcontext->revision_id = pci_config_get8(pci_cfg_hdl, PCI_CONF_REVID);
+
+ /*
+ * Refuse to work with dubious P3 cards.
+ */
+ if ((hwcontext->revision_id >= NX_P3_A0) &&
+ (hwcontext->revision_id < NX_P3_B1)) {
+ cmn_err(CE_WARN, "%s%d: NetXen chip revs between 0x%x-0x%x "
+ "is unsupported\n", adapter->name, adapter->instance,
+ NX_P3_A0, NX_P3_B0);
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Save error reporting settings; clear [19:16] error status bits.
+ * Set max read request [14:12] to 0 for 128 bytes. Set max payload
+ * size[7:5] to 0 for for 128 bytes.
+ */
+ if (NX_IS_REVISION_P2(hwcontext->revision_id)) {
+ pexsizes = pci_config_get32(pci_cfg_hdl, 0xd8);
+ pexsizes &= 7;
+ pexsizes |= 0xF0000;
+ pci_config_put32(pci_cfg_hdl, 0xd8, pexsizes);
+ }
+
+ pci_cmd_word = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
+ pci_cmd_word |= (PCI_COMM_INTX_DISABLE | PCI_COMM_SERR_ENABLE);
+ pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, pci_cmd_word);
+
+ if (hwcontext->revision_id >= NX_P3_B0)
+ legacy_intrp = &legacy_intr[hwcontext->pci_func];
+ else
+ legacy_intrp = &legacy_intr[0];
+
+ adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
+ adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
+ adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
+ adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
+
+ return (DDI_SUCCESS);
+}
+
+void
+unm_free_tx_dmahdl(unm_adapter *adapter)
+{
+ int i;
+ unm_dmah_node_t *nodep;
+
+ mutex_enter(&adapter->tx_lock);
+ nodep = &adapter->tx_dma_hdls[0];
+
+ for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
+ if (nodep->dmahdl != NULL) {
+ ddi_dma_free_handle(&nodep->dmahdl);
+ nodep->dmahdl = NULL;
+ }
+ nodep->next = NULL;
+ nodep++;
+ }
+
+ adapter->dmahdl_pool = NULL;
+ adapter->freehdls = 0;
+ mutex_exit(&adapter->tx_lock);
+}
+
+static int
+unm_alloc_tx_dmahdl(unm_adapter *adapter)
+{
+ int i;
+ unm_dmah_node_t *nodep = &adapter->tx_dma_hdls[0];
+
+ mutex_enter(&adapter->tx_lock);
+ for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) {
+ if (ddi_dma_alloc_handle(adapter->dip, &unm_dma_attr_cmddesc,
+ DDI_DMA_DONTWAIT, NULL, &nodep->dmahdl) != DDI_SUCCESS) {
+ mutex_exit(&adapter->tx_lock);
+ goto alloc_hdl_fail;
+ }
+
+ if (i > 0)
+ nodep->next = nodep - 1;
+ nodep++;
+ }
+
+ adapter->dmahdl_pool = nodep - 1;
+ adapter->freehdls = i;
+ mutex_exit(&adapter->tx_lock);
+
+ return (DDI_SUCCESS);
+
+alloc_hdl_fail:
+ unm_free_tx_dmahdl(adapter);
+ cmn_err(CE_WARN, "%s%d: Failed transmit ring dma handle allocation\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+}
+
+static void
+unm_free_dma_mem(dma_area_t *dma_p)
+{
+ if (dma_p->dma_hdl != NULL) {
+ if (dma_p->ncookies) {
+ (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
+ dma_p->ncookies = 0;
+ }
+ }
+ if (dma_p->acc_hdl != NULL) {
+ ddi_dma_mem_free(&dma_p->acc_hdl);
+ dma_p->acc_hdl = NULL;
+ }
+ if (dma_p->dma_hdl != NULL) {
+ ddi_dma_free_handle(&dma_p->dma_hdl);
+ dma_p->dma_hdl = NULL;
+ }
+}
+
+static int
+unm_alloc_dma_mem(unm_adapter *adapter, int size, uint_t dma_flag,
+ ddi_dma_attr_t *dma_attr_p, dma_area_t *dma_p)
+{
+ int ret;
+ caddr_t vaddr;
+ size_t actual_size;
+ ddi_dma_cookie_t cookie;
+
+ ret = ddi_dma_alloc_handle(adapter->dip,
+ dma_attr_p, DDI_DMA_DONTWAIT,
+ NULL, &dma_p->dma_hdl);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: Failed ddi_dma_alloc_handle\n",
+ adapter->name, adapter->instance);
+ goto dma_mem_fail;
+ }
+
+ ret = ddi_dma_mem_alloc(dma_p->dma_hdl,
+ size, &adapter->gc_attr_desc,
+ dma_flag & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
+ DDI_DMA_DONTWAIT, NULL, &vaddr, &actual_size,
+ &dma_p->acc_hdl);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() failed\n",
+ adapter->name, adapter->instance);
+ goto dma_mem_fail;
+ }
+
+ if (actual_size < size) {
+ cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() allocated small\n",
+ adapter->name, adapter->instance);
+ goto dma_mem_fail;
+ }
+
+ ret = ddi_dma_addr_bind_handle(dma_p->dma_hdl,
+ NULL, vaddr, size, dma_flag, DDI_DMA_DONTWAIT,
+ NULL, &cookie, &dma_p->ncookies);
+ if (ret != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
+ cmn_err(CE_WARN, "%s%d: ddi_dma_addr_bind_handle() failed, "
+ "%d, %d\n", adapter->name, adapter->instance, ret,
+ dma_p->ncookies);
+ goto dma_mem_fail;
+ }
+
+ dma_p->dma_addr = cookie.dmac_laddress;
+ dma_p->vaddr = vaddr;
+ (void) memset(vaddr, 0, size);
+
+ return (DDI_SUCCESS);
+
+dma_mem_fail:
+ unm_free_dma_mem(dma_p);
+ return (DDI_FAILURE);
+}
+
+void
+unm_free_tx_buffers(unm_adapter *adapter)
+{
+ int i;
+ dma_area_t *dma_p;
+ struct unm_cmd_buffer *cmd_buf;
+ unm_dmah_node_t *nodep;
+
+ cmd_buf = &adapter->cmd_buf_arr[0];
+
+ for (i = 0; i < adapter->MaxTxDescCount; i++) {
+ dma_p = &cmd_buf->dma_area;
+ unm_free_dma_mem(dma_p);
+ nodep = cmd_buf->head;
+ while (nodep != NULL) {
+ (void) ddi_dma_unbind_handle(nodep->dmahdl);
+ nodep = nodep->next;
+ }
+ if (cmd_buf->msg != NULL)
+ freemsg(cmd_buf->msg);
+ cmd_buf++;
+ }
+ adapter->freecmds = 0;
+}
+
+static int
+unm_alloc_tx_buffers(unm_adapter *adapter)
+{
+ int i, ret, size, allocated = 0;
+ dma_area_t *dma_p;
+ struct unm_cmd_buffer *cmd_buf;
+
+ cmd_buf = &adapter->cmd_buf_arr[0];
+ size = adapter->maxmtu;
+
+ for (i = 0; i < adapter->MaxTxDescCount; i++) {
+ dma_p = &cmd_buf->dma_area;
+ ret = unm_alloc_dma_mem(adapter, size,
+ DDI_DMA_WRITE | DDI_DMA_STREAMING,
+ &unm_dma_attr_rxbuf, dma_p);
+ if (ret != DDI_SUCCESS)
+ goto alloc_tx_buffer_fail;
+
+ allocated++;
+ cmd_buf++;
+ }
+ adapter->freecmds = adapter->MaxTxDescCount;
+ return (DDI_SUCCESS);
+
+alloc_tx_buffer_fail:
+
+ cmd_buf = &adapter->cmd_buf_arr[0];
+ for (i = 0; i < allocated; i++) {
+ dma_p = &cmd_buf->dma_area;
+ unm_free_dma_mem(dma_p);
+ cmd_buf++;
+ }
+ cmn_err(CE_WARN, "%s%d: Failed transmit ring memory allocation\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+}
+
+/*
+ * Called by freemsg() to "free" the resource.
+ */
+static void
+unm_rx_buffer_recycle(char *arg)
+{
+ unm_rx_buffer_t *rx_buffer = (unm_rx_buffer_t *)(uintptr_t)arg;
+ unm_adapter *adapter = rx_buffer->adapter;
+ unm_rcv_desc_ctx_t *rcv_desc = rx_buffer->rcv_desc;
+
+ rx_buffer->mp = desballoc(rx_buffer->dma_info.vaddr,
+ rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
+
+ if (rx_buffer->mp == NULL)
+ adapter->stats.desballocfailed++;
+
+ mutex_enter(rcv_desc->recycle_lock);
+ rx_buffer->next = rcv_desc->recycle_list;
+ rcv_desc->recycle_list = rx_buffer;
+ rcv_desc->rx_buf_recycle++;
+ mutex_exit(rcv_desc->recycle_lock);
+}
+
+void
+unm_destroy_rx_ring(unm_rcv_desc_ctx_t *rcv_desc)
+{
+ uint32_t i, total_buf;
+ unm_rx_buffer_t *buf_pool;
+
+ total_buf = rcv_desc->rx_buf_total;
+ buf_pool = rcv_desc->rx_buf_pool;
+ for (i = 0; i < total_buf; i++) {
+ if (buf_pool->mp != NULL)
+ freemsg(buf_pool->mp);
+ unm_free_dma_mem(&buf_pool->dma_info);
+ buf_pool++;
+ }
+
+ kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
+ rcv_desc->rx_buf_pool = NULL;
+ rcv_desc->pool_list = NULL;
+ rcv_desc->recycle_list = NULL;
+ rcv_desc->rx_buf_free = 0;
+
+ mutex_destroy(rcv_desc->pool_lock);
+ mutex_destroy(rcv_desc->recycle_lock);
+}
+
+static int
+unm_create_rx_ring(unm_adapter *adapter, unm_rcv_desc_ctx_t *rcv_desc)
+{
+ int i, ret, allocate = 0, sreoff;
+ uint32_t total_buf;
+ dma_area_t *dma_info;
+ unm_rx_buffer_t *rx_buffer;
+
+ sreoff = adapter->ahw.cut_through ? 0 : IP_ALIGNMENT_BYTES;
+
+ /* temporarily set the total rx buffers two times of MaxRxDescCount */
+ total_buf = rcv_desc->rx_buf_total = rcv_desc->MaxRxDescCount * 2;
+
+ rcv_desc->rx_buf_pool = kmem_zalloc(sizeof (unm_rx_buffer_t) *
+ total_buf, KM_SLEEP);
+ rx_buffer = rcv_desc->rx_buf_pool;
+ for (i = 0; i < total_buf; i++) {
+ dma_info = &rx_buffer->dma_info;
+ ret = unm_alloc_dma_mem(adapter, rcv_desc->buf_size,
+ DDI_DMA_READ | DDI_DMA_STREAMING,
+ &unm_dma_attr_rxbuf, dma_info);
+ if (ret != DDI_SUCCESS)
+ goto alloc_mem_failed;
+ else {
+ allocate++;
+ dma_info->vaddr = (void *) ((char *)dma_info->vaddr +
+ sreoff);
+ dma_info->dma_addr += sreoff;
+ rx_buffer->rx_recycle.free_func =
+ unm_rx_buffer_recycle;
+ rx_buffer->rx_recycle.free_arg = (caddr_t)rx_buffer;
+ rx_buffer->next = NULL;
+ rx_buffer->mp = desballoc(dma_info->vaddr,
+ rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
+ if (rx_buffer->mp == NULL)
+ adapter->stats.desballocfailed++;
+ rx_buffer->rcv_desc = rcv_desc;
+ rx_buffer->adapter = adapter;
+ rx_buffer++;
+ }
+ }
+
+ for (i = 0; i < (total_buf - 1); i++) {
+ rcv_desc->rx_buf_pool[i].next = &rcv_desc->rx_buf_pool[i + 1];
+ }
+
+ rcv_desc->pool_list = rcv_desc->rx_buf_pool;
+ rcv_desc->recycle_list = NULL;
+ rcv_desc->rx_buf_free = total_buf;
+
+ mutex_init(rcv_desc->pool_lock, NULL,
+ MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
+ mutex_init(rcv_desc->recycle_lock, NULL,
+ MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
+
+ return (DDI_SUCCESS);
+
+alloc_mem_failed:
+ rx_buffer = rcv_desc->rx_buf_pool;
+ for (i = 0; i < allocate; i++, rx_buffer++) {
+ dma_info = &rx_buffer->dma_info;
+ if (rx_buffer->mp != NULL)
+ freemsg(rx_buffer->mp);
+ unm_free_dma_mem(dma_info);
+ }
+
+ kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf);
+ rcv_desc->rx_buf_pool = NULL;
+
+ cmn_err(CE_WARN, "%s%d: Failed receive ring resource allocation\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+}
+
+static void
+unm_check_options(unm_adapter *adapter)
+{
+ int i, ring, tx_desc, rx_desc, rx_jdesc;
+ unm_recv_context_t *recv_ctx;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ uint8_t revid = adapter->ahw.revision_id;
+ dev_info_t *dip = adapter->dip;
+
+ verbmsg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ dmesg_propname, 0);
+
+ adapter->tx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
+ dip, DDI_PROP_DONTPASS, txbcopythreshold_propname,
+ UNM_TX_BCOPY_THRESHOLD);
+ adapter->rx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY,
+ dip, DDI_PROP_DONTPASS, rxbcopythreshold_propname,
+ UNM_RX_BCOPY_THRESHOLD);
+
+ tx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ txringsize_propname, MAX_CMD_DESCRIPTORS_HOST);
+ if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS &&
+ !(tx_desc & (tx_desc - 1))) {
+ adapter->MaxTxDescCount = tx_desc;
+ } else {
+ cmn_err(CE_WARN, "%s%d: TxRingSize defaulting to %d, since "
+ ".conf value is not 2 power aligned in range 256 - %d\n",
+ adapter->name, adapter->instance, MAX_CMD_DESCRIPTORS_HOST,
+ MAX_CMD_DESCRIPTORS);
+ adapter->MaxTxDescCount = MAX_CMD_DESCRIPTORS_HOST;
+ }
+
+ rx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ rxringsize_propname, MAX_RCV_DESCRIPTORS);
+ if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE &&
+ rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE &&
+ !(rx_desc & (rx_desc - 1))) {
+ adapter->MaxRxDescCount = rx_desc;
+ } else {
+ cmn_err(CE_WARN, "%s%d: RxRingSize defaulting to %d, since "
+ ".conf value is not 2 power aligned in range %d - %d\n",
+ adapter->name, adapter->instance, MAX_RCV_DESCRIPTORS,
+ NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_RDS_SIZE);
+ adapter->MaxRxDescCount = MAX_RCV_DESCRIPTORS;
+ }
+
+ rx_jdesc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ jumborxringsize_propname, MAX_JUMBO_RCV_DESCRIPTORS);
+ if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE &&
+ rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE &&
+ !(rx_jdesc & (rx_jdesc - 1))) {
+ adapter->MaxJumboRxDescCount = rx_jdesc;
+ } else {
+ cmn_err(CE_WARN, "%s%d: JumboRingSize defaulting to %d, since "
+ ".conf value is not 2 power aligned in range %d - %d\n",
+ adapter->name, adapter->instance, MAX_JUMBO_RCV_DESCRIPTORS,
+ NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE);
+ adapter->MaxJumboRxDescCount = MAX_JUMBO_RCV_DESCRIPTORS;
+ }
+
+ adapter->MaxLroRxDescCount = MAX_LRO_RCV_DESCRIPTORS;
+
+ adapter->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, defaultmtu_propname, MTU_SIZE);
+
+ if (adapter->mtu < MTU_SIZE) {
+ cmn_err(CE_WARN, "Raising mtu to %d\n", MTU_SIZE);
+ adapter->mtu = MTU_SIZE;
+ }
+ adapter->maxmtu = NX_IS_REVISION_P2(revid) ? P2_MAX_MTU : P3_MAX_MTU;
+ if (adapter->mtu > adapter->maxmtu) {
+ cmn_err(CE_WARN, "Lowering mtu to %d\n", adapter->maxmtu);
+ adapter->mtu = adapter->maxmtu;
+ }
+
+ adapter->maxmtu += NX_MAX_ETHERHDR;
+
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ recv_ctx = &adapter->recv_ctx[i];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+
+ switch (RCV_DESC_TYPE(ring)) {
+ case RCV_DESC_NORMAL:
+ rcv_desc->MaxRxDescCount =
+ adapter->MaxRxDescCount;
+ if (adapter->ahw.cut_through) {
+ rcv_desc->dma_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ rcv_desc->buf_size = rcv_desc->dma_size;
+ } else {
+ rcv_desc->dma_size =
+ NX_RX_NORMAL_BUF_MAX_LEN;
+ rcv_desc->buf_size =
+ rcv_desc->dma_size +
+ IP_ALIGNMENT_BYTES;
+ }
+ break;
+
+ case RCV_DESC_JUMBO:
+ rcv_desc->MaxRxDescCount =
+ adapter->MaxJumboRxDescCount;
+ if (adapter->ahw.cut_through) {
+ rcv_desc->dma_size =
+ rcv_desc->buf_size =
+ NX_P3_RX_JUMBO_BUF_MAX_LEN;
+ } else {
+ if (NX_IS_REVISION_P2(revid))
+ rcv_desc->dma_size =
+ NX_P2_RX_JUMBO_BUF_MAX_LEN;
+ else
+ rcv_desc->dma_size =
+ NX_P3_RX_JUMBO_BUF_MAX_LEN;
+ rcv_desc->buf_size =
+ rcv_desc->dma_size +
+ IP_ALIGNMENT_BYTES;
+ }
+ break;
+
+ case RCV_RING_LRO:
+ rcv_desc->MaxRxDescCount =
+ adapter->MaxLroRxDescCount;
+ rcv_desc->buf_size = MAX_RX_LRO_BUFFER_LENGTH;
+ rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static void
+vector128M(unm_adapter *aptr)
+{
+ aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_128M;
+ aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_128M;
+ aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_128M;
+ aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_128M;
+ aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_ioctl_128M;
+ aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_ioctl_128M;
+ aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_128M;
+ aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_128M;
+ aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_128M;
+ aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_128M;
+ aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_128M;
+ aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_128M;
+ aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_128M;
+ aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_128M;
+ aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_128M;
+}
+
+static void
+vector2M(unm_adapter *aptr)
+{
+ aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_2M;
+ aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_2M;
+ aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_2M;
+ aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_2M;
+ aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_wx_2M;
+ aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_wx_2M;
+ aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_2M;
+ aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_2M;
+ aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_2M;
+ aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_2M;
+ aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_2M;
+ aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_2M;
+ aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_2M;
+ aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_2M;
+ aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_2M;
+}
+
+static int
+unm_pci_map_setup(unm_adapter *adapter)
+{
+ int ret;
+ caddr_t reg_base, db_base;
+ caddr_t mem_ptr0, mem_ptr1 = NULL, mem_ptr2 = NULL;
+ unsigned long pci_len0;
+ unsigned long first_page_group_start, first_page_group_end;
+
+ off_t regsize, dbsize = UNM_DB_MAPSIZE_BYTES;
+ dev_info_t *dip = adapter->dip;
+
+ adapter->ahw.qdr_sn_window = adapter->ahw.ddr_mn_window = -1;
+
+ /* map register space */
+
+ ret = ddi_dev_regsize(dip, 1, &regsize);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: failed to read reg size for bar0\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ ret = ddi_regs_map_setup(dip, 1, &reg_base, 0,
+ regsize, &unm_dev_attr, &adapter->regs_handle);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: failed to map registers\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ mem_ptr0 = reg_base;
+
+ if (regsize == UNM_PCI_128MB_SIZE) {
+ pci_len0 = FIRST_PAGE_GROUP_SIZE;
+ mem_ptr1 = mem_ptr0 + SECOND_PAGE_GROUP_START;
+ mem_ptr2 = mem_ptr0 + THIRD_PAGE_GROUP_START;
+ first_page_group_start = FIRST_PAGE_GROUP_START;
+ first_page_group_end = FIRST_PAGE_GROUP_END;
+ vector128M(adapter);
+ } else if (regsize == UNM_PCI_32MB_SIZE) {
+ pci_len0 = 0;
+ mem_ptr1 = mem_ptr0;
+ mem_ptr2 = mem_ptr0 +
+ (THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START);
+ first_page_group_start = 0;
+ first_page_group_end = 0;
+ vector128M(adapter);
+ } else if (regsize == UNM_PCI_2MB_SIZE) {
+ pci_len0 = UNM_PCI_2MB_SIZE;
+ first_page_group_start = 0;
+ first_page_group_end = 0;
+ adapter->ahw.ddr_mn_window = adapter->ahw.qdr_sn_window = 0;
+ adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
+ (adapter->ahw.pci_func * 0x20);
+ if (adapter->ahw.pci_func < 4)
+ adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
+ (adapter->ahw.pci_func * 0x20);
+ else
+ adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW +
+ 0xA0 + ((adapter->ahw.pci_func - 4) * 0x10);
+ vector2M(adapter);
+ } else {
+ cmn_err(CE_WARN, "%s%d: invalid pci regs map size %ld\n",
+ adapter->name, adapter->instance, regsize);
+ ddi_regs_map_free(&adapter->regs_handle);
+ return (DDI_FAILURE);
+ }
+
+ adapter->ahw.pci_base0 = (unsigned long)mem_ptr0;
+ adapter->ahw.pci_len0 = pci_len0;
+ adapter->ahw.pci_base1 = (unsigned long)mem_ptr1;
+ adapter->ahw.pci_len1 = SECOND_PAGE_GROUP_SIZE;
+ adapter->ahw.pci_base2 = (unsigned long)mem_ptr2;
+ adapter->ahw.pci_len2 = THIRD_PAGE_GROUP_SIZE;
+ adapter->ahw.crb_base =
+ PCI_OFFSET_SECOND_RANGE(adapter, UNM_PCI_CRBSPACE);
+
+ adapter->ahw.first_page_group_start = first_page_group_start;
+ adapter->ahw.first_page_group_end = first_page_group_end;
+
+ /* map doorbell */
+
+ ret = ddi_regs_map_setup(dip, 2, &db_base, 0,
+ dbsize, &unm_dev_attr, &adapter->db_handle);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: failed to map doorbell\n",
+ adapter->name, adapter->instance);
+ ddi_regs_map_free(&adapter->regs_handle);
+ return (DDI_FAILURE);
+ }
+
+ adapter->ahw.db_base = (unsigned long)db_base;
+ adapter->ahw.db_len = dbsize;
+
+ return (DDI_SUCCESS);
+}
+
+static int
+unm_initialize_intr(unm_adapter *adapter)
+{
+
+ int ret;
+ int type, count, avail, actual;
+
+ ret = ddi_intr_get_supported_types(adapter->dip, &type);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: ddi_intr_get_supported_types() "
+ "failed\n", adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ type = DDI_INTR_TYPE_MSI;
+ ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
+ if ((ret == DDI_SUCCESS) && (count > 0))
+ goto found_msi;
+
+ type = DDI_INTR_TYPE_FIXED;
+ ret = ddi_intr_get_nintrs(adapter->dip, type, &count);
+ if ((ret != DDI_SUCCESS) || (count == 0)) {
+ cmn_err(CE_WARN,
+ "ddi_intr_get_nintrs() failure ret=%d\n", ret);
+ return (DDI_FAILURE);
+ }
+
+found_msi:
+ adapter->intr_type = type;
+ adapter->flags &= ~(UNM_NIC_MSI_ENABLED | UNM_NIC_MSIX_ENABLED);
+ if (type == DDI_INTR_TYPE_MSI)
+ adapter->flags |= UNM_NIC_MSI_ENABLED;
+
+ /* Get number of available interrupts */
+ ret = ddi_intr_get_navail(adapter->dip, type, &avail);
+ if ((ret != DDI_SUCCESS) || (avail == 0)) {
+ cmn_err(CE_WARN, "ddi_intr_get_navail() failure, ret=%d\n",
+ ret);
+ return (DDI_FAILURE);
+ }
+
+ ret = ddi_intr_alloc(adapter->dip, &adapter->intr_handle,
+ type, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
+ if ((ret != DDI_SUCCESS) || (actual == 0)) {
+ cmn_err(CE_WARN, "ddi_intr_alloc() failure: %d\n", ret);
+ return (DDI_FAILURE);
+ }
+
+ ret = ddi_intr_get_pri(adapter->intr_handle, &adapter->intr_pri);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "ddi_intr_get_pri() failure: %d\n", ret);
+ }
+
+ /* Call ddi_intr_add_handler() */
+ ret = ddi_intr_add_handler(adapter->intr_handle, unm_intr,
+ (caddr_t)adapter, NULL);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: ddi_intr_add_handler() failure\n",
+ adapter->name, adapter->instance);
+ (void) ddi_intr_free(adapter->intr_handle);
+ return (DDI_FAILURE);
+ }
+
+ /* Add softintr if required */
+
+ return (DDI_SUCCESS);
+
+}
+
+void
+unm_destroy_intr(unm_adapter *adapter)
+{
+ /* disable interrupt */
+ if (adapter->intr_type == DDI_INTR_TYPE_MSI)
+ (void) ddi_intr_block_disable(&adapter->intr_handle, 1);
+ else
+ (void) ddi_intr_disable(adapter->intr_handle);
+
+ (void) ddi_intr_remove_handler(adapter->intr_handle);
+ (void) ddi_intr_free(adapter->intr_handle);
+
+ /* Remove the software intr handler */
+}
+
+static void
+netxen_set_port_mode(unm_adapter *adapter)
+{
+ static int wol_port_mode = UNM_PORT_MODE_AUTO_NEG_1G;
+ static int port_mode = UNM_PORT_MODE_AUTO_NEG;
+ int btype = adapter->ahw.boardcfg.board_type, data = 0;
+
+ if (btype == UNM_BRDTYPE_P3_HMEZ || btype == UNM_BRDTYPE_P3_XG_LOM) {
+ data = port_mode; /* set to port_mode normally */
+ if ((port_mode != UNM_PORT_MODE_802_3_AP) &&
+ (port_mode != UNM_PORT_MODE_XG) &&
+ (port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
+ (port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
+ data = UNM_PORT_MODE_AUTO_NEG;
+
+ adapter->unm_nic_hw_write_wx(adapter, UNM_PORT_MODE_ADDR,
+ &data, 4);
+
+ if ((wol_port_mode != UNM_PORT_MODE_802_3_AP) &&
+ (wol_port_mode != UNM_PORT_MODE_XG) &&
+ (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
+ (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_XG))
+ wol_port_mode = UNM_PORT_MODE_AUTO_NEG;
+
+ adapter->unm_nic_hw_write_wx(adapter, UNM_WOL_PORT_MODE,
+ &wol_port_mode, 4);
+ }
+}
+
+static void
+netxen_pcie_strap_init(unm_adapter *adapter)
+{
+ ddi_acc_handle_t pcihdl = adapter->pci_cfg_handle;
+ u32 chicken, control, c8c9value = 0xF1000;
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
+ &chicken, 4);
+
+ chicken &= 0xFCFFFFFF; /* clear chicken3 25:24 */
+ control = pci_config_get32(pcihdl, 0xD0);
+ if ((control & 0x000F0000) != 0x00020000) /* is it gen1? */
+ chicken |= 0x01000000;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3),
+ &chicken, 4);
+ control = pci_config_get32(pcihdl, 0xC8);
+ control = pci_config_get32(pcihdl, 0xC8);
+ pci_config_put32(pcihdl, 0xC8, c8c9value);
+}
+
+static int
+netxen_read_mac_addr(unm_adapter *adapter)
+{
+ u64 mac_addr[FLASH_NUM_PORTS + 1];
+ unsigned char *p;
+ int i;
+
+ if (is_flash_supported(adapter) != 0)
+ return (-1);
+
+ if (get_flash_mac_addr(adapter, mac_addr) != 0)
+ return (-1);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ p = (unsigned char *)&mac_addr[adapter->ahw.pci_func];
+ else
+ p = (unsigned char *)&mac_addr[adapter->portnum];
+
+ for (i = 0; i < 6; i++)
+ adapter->mac_addr[i] = p[5 - i];
+
+ if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0)
+ return (-1);
+
+ return (0);
+}
+
+static int
+unmattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ unm_adapter *adapter;
+ unm_recv_context_t *recv_ctx = NULL;
+ unm_rcv_desc_ctx_t *rcv_desc = NULL;
+ int i, first_driver = 0;
+ int ret, ring, temp;
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ case DDI_PM_RESUME:
+ default:
+ return (DDI_FAILURE);
+ }
+
+ adapter = kmem_zalloc(sizeof (unm_adapter), KM_SLEEP);
+ adapter->dip = dip;
+ ddi_set_driver_private(dip, adapter);
+ adapter->instance = ddi_get_instance(dip);
+
+ adapter->name = ddi_driver_name(dip);
+
+ ret = pci_config_setup(dip, &adapter->pci_cfg_handle);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: pci_config_setup failed\n",
+ adapter->name, adapter->instance);
+ goto attach_setup_err;
+ }
+
+ ret = unm_pci_cfg_init(adapter);
+ if (ret != DDI_SUCCESS)
+ goto attach_err;
+
+ ret = unm_pci_map_setup(adapter);
+ if (ret != DDI_SUCCESS)
+ goto attach_err;
+
+ if (unm_initialize_intr(adapter) != DDI_SUCCESS)
+ goto attach_unmap_regs;
+
+ rw_init(&adapter->adapter_lock, NULL,
+ RW_DRIVER, DDI_INTR_PRI(adapter->intr_pri));
+ mutex_init(&adapter->tx_lock, NULL,
+ MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
+ mutex_init(&adapter->lock, NULL,
+ MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri)));
+
+ adapter->portnum = (int8_t)adapter->ahw.pci_func;
+
+ /*
+ * Set the CRB window to invalid. If any register in window 0 is
+ * accessed it should set window to 0 and then reset it to 1.
+ */
+ adapter->curr_window = 255;
+
+ adapter->fw_major = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_FW_VERSION_MAJOR);
+
+ if (adapter->fw_major < 4)
+ adapter->max_rds_rings = 3;
+ else
+ adapter->max_rds_rings = 2;
+
+ STRUCT_COPY(adapter->gc_dma_attr_desc, unm_dma_attr_desc);
+ STRUCT_COPY(adapter->gc_attr_desc, unm_buf_attr);
+
+ ret = unm_nic_get_board_info(adapter);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: error reading board config\n",
+ adapter->name, adapter->instance);
+ goto attach_destroy_intr;
+ }
+
+ /* Mezz cards have PCI function 0, 2, 3 enabled */
+ switch (adapter->ahw.boardcfg.board_type) {
+ case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
+ case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
+ if (adapter->ahw.pci_func >= 2) {
+ adapter->portnum = adapter->ahw.pci_func - 2;
+ }
+ default:
+ break;
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ temp = UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL, adapter);
+ adapter->ahw.cut_through = NX_IS_SYSTEM_CUT_THROUGH(temp);
+ if (adapter->ahw.pci_func == 0)
+ first_driver = 1;
+ } else {
+ if (adapter->portnum == 0)
+ first_driver = 1;
+ }
+
+ unm_check_options(adapter);
+
+ if (first_driver) {
+ int first_boot = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_CAM_RAM(0x1fc));
+
+ if (check_hw_init(adapter) != 0) {
+ cmn_err(CE_WARN, "%s%d: Error in HW init sequence\n",
+ adapter->name, adapter->instance);
+ goto attach_destroy_intr;
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_set_port_mode(adapter);
+
+ if (first_boot != 0x55555555) {
+ temp = 0;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE,
+ &temp, 4);
+ if (pinit_from_rom(adapter, 0) != 0)
+ goto attach_destroy_intr;
+
+ drv_usecwait(500);
+
+ ret = load_from_flash(adapter);
+ if (ret != DDI_SUCCESS)
+ goto attach_destroy_intr;
+ }
+
+ if (ret = unm_initialize_dummy_dma(adapter))
+ goto attach_destroy_intr;
+
+ /*
+ * Tell the hardware our version number.
+ */
+ i = (_UNM_NIC_MAJOR << 16) |
+ ((_UNM_NIC_MINOR << 8)) | (_UNM_NIC_SUBVERSION);
+ adapter->unm_nic_hw_write_wx(adapter, CRB_DRIVER_VERSION,
+ &i, 4);
+
+ /* Unlock the HW, prompting the boot sequence */
+ if ((first_boot == 0x55555555) &&
+ (NX_IS_REVISION_P2(adapter->ahw.revision_id)))
+ adapter->unm_nic_pci_write_normalize(adapter,
+ UNM_ROMUSB_GLB_PEGTUNE_DONE, 1);
+
+ /* Handshake with the card before we register the devices. */
+ if (phantom_init(adapter, 0) != DDI_SUCCESS)
+ goto attach_destroy_intr;
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_pcie_strap_init(adapter);
+
+ /*
+ * See if the firmware gave us a virtual-physical port mapping.
+ */
+ adapter->physical_port = adapter->portnum;
+ i = adapter->unm_nic_pci_read_normalize(adapter,
+ CRB_V2P(adapter->portnum));
+ if (i != 0x55555555)
+ adapter->physical_port = (uint16_t)i;
+
+ adapter->cmd_buf_arr = (struct unm_cmd_buffer *)kmem_zalloc(
+ sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount,
+ KM_SLEEP);
+
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ recv_ctx = &adapter->recv_ctx[i];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ ret = unm_create_rx_ring(adapter, rcv_desc);
+ if (ret != DDI_SUCCESS)
+ goto attach_free_cmdbufs;
+ }
+ }
+
+ ret = unm_alloc_tx_dmahdl(adapter);
+ if (ret != DDI_SUCCESS)
+ goto attach_free_cmdbufs;
+
+ ret = unm_alloc_tx_buffers(adapter);
+ if (ret != DDI_SUCCESS)
+ goto attach_free_tx_dmahdl;
+
+ adapter->ahw.linkup = 0;
+
+ if (receive_peg_ready(adapter)) {
+ ret = -EIO;
+ goto attach_free_tx_buffers;
+ }
+
+ if (netxen_read_mac_addr(adapter))
+ cmn_err(CE_WARN, "%s%d: Failed to read MAC addr\n",
+ adapter->name, adapter->instance);
+
+ unm_nic_flash_print(adapter);
+
+ if (verbmsg != 0) {
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ cmn_err(CE_NOTE, "%s: QUAD GbE port %d initialized\n",
+ unm_nic_driver_name, adapter->portnum);
+ break;
+
+ case UNM_NIC_XGBE:
+ cmn_err(CE_NOTE, "%s: XGbE port %d initialized\n",
+ unm_nic_driver_name, adapter->portnum);
+ break;
+ }
+ }
+
+ ret = unm_register_mac(adapter);
+ if (ret != DDI_SUCCESS) {
+ cmn_err(CE_NOTE, "%s%d: Mac registration error\n",
+ adapter->name, adapter->instance);
+ goto attach_free_tx_buffers;
+ }
+
+ return (DDI_SUCCESS);
+
+attach_free_tx_buffers:
+ unm_free_tx_buffers(adapter);
+attach_free_tx_dmahdl:
+ unm_free_tx_dmahdl(adapter);
+attach_free_cmdbufs:
+ kmem_free(adapter->cmd_buf_arr, sizeof (struct unm_cmd_buffer) *
+ adapter->MaxTxDescCount);
+ for (i = 0; i < MAX_RCV_CTX; ++i) {
+ recv_ctx = &adapter->recv_ctx[i];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ if (rcv_desc->rx_buf_pool != NULL)
+ unm_destroy_rx_ring(rcv_desc);
+ }
+ }
+
+ if (adapter->portnum == 0)
+ unm_free_dummy_dma(adapter);
+attach_destroy_intr:
+ unm_destroy_intr(adapter);
+attach_unmap_regs:
+ ddi_regs_map_free(&(adapter->regs_handle));
+ ddi_regs_map_free(&(adapter->db_handle));
+attach_err:
+ pci_config_teardown(&adapter->pci_cfg_handle);
+attach_setup_err:
+ kmem_free(adapter, sizeof (unm_adapter));
+ return (ret);
+}
+
+static int
+unmdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ unm_adapter *adapter = (unm_adapter *)ddi_get_driver_private(dip);
+
+ if (adapter == NULL)
+ return (DDI_FAILURE);
+
+ switch (cmd) {
+ case DDI_DETACH:
+
+ unm_fini_kstats(adapter);
+ adapter->kstats[0] = NULL;
+
+ if (adapter->pci_cfg_handle != NULL)
+ pci_config_teardown(&adapter->pci_cfg_handle);
+
+ unm_nd_cleanup(adapter);
+ unm_nic_remove(adapter);
+ return (DDI_SUCCESS);
+
+ case DDI_SUSPEND:
+ return (unm_nic_suspend(adapter));
+
+ default:
+ break;
+ }
+
+ return (DDI_FAILURE);
+}
+
+#ifdef SOLARIS11
+DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
+ nodev, NULL, D_MP, NULL, NULL);
+#else
+DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach,
+ nodev, NULL, D_MP, NULL);
+#endif
+
+static struct modldrv modldrv = {
+ &mod_driverops, /* Type of module. This one is a driver */
+ ident,
+ &unm_ops, /* driver ops */
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ (&modldrv),
+ NULL
+};
+
+
+int
+_init(void)
+{
+ int ret;
+
+ unm_ops.devo_cb_ops->cb_str = NULL;
+ mac_init_ops(&unm_ops, "ntxn");
+
+ ret = mod_install(&modlinkage);
+ if (ret != DDI_SUCCESS) {
+ mac_fini_ops(&unm_ops);
+ cmn_err(CE_WARN, "ntxn: mod_install failed\n");
+ }
+
+ return (ret);
+}
+
+
+int
+_fini(void)
+{
+ int ret;
+
+ ret = mod_remove(&modlinkage);
+ if (ret == DDI_SUCCESS)
+ mac_fini_ops(&unm_ops);
+ return (ret);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_inc.h b/usr/src/uts/common/io/ntxn/unm_inc.h
new file mode 100644
index 0000000000..9d06d87ef5
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_inc.h
@@ -0,0 +1,1777 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __UNM_INC_H
+#define __UNM_INC_H
+
+#include "nx_errorcode.h"
+
+#define PREALIGN(x)
+#define POSTALIGN(x)
+
+typedef char __int8_t;
+typedef short __int16_t;
+typedef int __int32_t;
+typedef long long __int64_t;
+typedef unsigned char __uint8_t;
+typedef unsigned short __uint16_t;
+typedef unsigned int __uint32_t;
+typedef unsigned long long __uint64_t;
+typedef __uint64_t jiffies_t;
+
+typedef uint8_t u8;
+typedef uint8_t U8;
+typedef uint16_t U16;
+typedef uint32_t u32;
+typedef uint32_t U32;
+typedef unsigned long long u64;
+typedef unsigned long long U64;
+
+#define UNUSED __attribute__((unused))
+#define NOINLINE __attribute__((noinline))
+
+#include "nx_hw_pci_regs.h"
+
+#define UNM_CONF_X86 3
+
+#define bzero(A, B) memset((A), 0, (B))
+
+/*
+ * MAX_RCV_CTX : The number of receive contexts that are available on
+ * the phantom.
+ */
+#define MAX_RCV_CTX 1
+
+/* ------------------------------------------------------------------------ */
+/* CRB Hub and Agent addressing */
+/* ------------------------------------------------------------------------ */
+/*
+ * WARNING: pex_tgt_adr.v assumes if MSB of hub adr is set then it is an
+ * ILLEGAL hub!!!!!
+ */
+#define UNM_HW_H0_CH_HUB_ADR 0x05
+#define UNM_HW_H1_CH_HUB_ADR 0x0E
+#define UNM_HW_H2_CH_HUB_ADR 0x03
+#define UNM_HW_H3_CH_HUB_ADR 0x01
+#define UNM_HW_H4_CH_HUB_ADR 0x06
+#define UNM_HW_H5_CH_HUB_ADR 0x07
+#define UNM_HW_H6_CH_HUB_ADR 0x08
+/*
+ * WARNING: pex_tgt_adr.v assumes if MSB of hub adr is set then it is an
+ * ILLEGAL hub!!!!!
+ */
+
+/* Hub 0 */
+#define UNM_HW_MN_CRB_AGT_ADR 0x15
+#define UNM_HW_MS_CRB_AGT_ADR 0x25
+
+/* Hub 1 */
+#define UNM_HW_PS_CRB_AGT_ADR 0x73
+#define UNM_HW_SS_CRB_AGT_ADR 0x20
+#define UNM_HW_RPMX3_CRB_AGT_ADR 0x0b
+#define UNM_HW_QMS_CRB_AGT_ADR 0x00
+#define UNM_HW_SQGS0_CRB_AGT_ADR 0x01
+#define UNM_HW_SQGS1_CRB_AGT_ADR 0x02
+#define UNM_HW_SQGS2_CRB_AGT_ADR 0x03
+#define UNM_HW_SQGS3_CRB_AGT_ADR 0x04
+#define UNM_HW_C2C0_CRB_AGT_ADR 0x58
+#define UNM_HW_C2C1_CRB_AGT_ADR 0x59
+#define UNM_HW_C2C2_CRB_AGT_ADR 0x5a
+#define UNM_HW_RPMX2_CRB_AGT_ADR 0x0a
+#define UNM_HW_RPMX4_CRB_AGT_ADR 0x0c
+#define UNM_HW_RPMX7_CRB_AGT_ADR 0x0f
+#define UNM_HW_RPMX9_CRB_AGT_ADR 0x12
+#define UNM_HW_SMB_CRB_AGT_ADR 0x18
+
+/* Hub 2 */
+#define UNM_HW_NIU_CRB_AGT_ADR 0x31
+#define UNM_HW_I2C0_CRB_AGT_ADR 0x19
+#define UNM_HW_I2C1_CRB_AGT_ADR 0x29
+
+#define UNM_HW_SN_CRB_AGT_ADR 0x10
+#define UNM_HW_I2Q_CRB_AGT_ADR 0x20
+#define UNM_HW_LPC_CRB_AGT_ADR 0x22
+#define UNM_HW_ROMUSB_CRB_AGT_ADR 0x21
+#define UNM_HW_QM_CRB_AGT_ADR 0x66
+#define UNM_HW_SQG0_CRB_AGT_ADR 0x60
+#define UNM_HW_SQG1_CRB_AGT_ADR 0x61
+#define UNM_HW_SQG2_CRB_AGT_ADR 0x62
+#define UNM_HW_SQG3_CRB_AGT_ADR 0x63
+#define UNM_HW_RPMX1_CRB_AGT_ADR 0x09
+#define UNM_HW_RPMX5_CRB_AGT_ADR 0x0d
+#define UNM_HW_RPMX6_CRB_AGT_ADR 0x0e
+#define UNM_HW_RPMX8_CRB_AGT_ADR 0x11
+
+/* Hub 3 */
+#define UNM_HW_PH_CRB_AGT_ADR 0x1A
+#define UNM_HW_SRE_CRB_AGT_ADR 0x50
+#define UNM_HW_EG_CRB_AGT_ADR 0x51
+#define UNM_HW_RPMX0_CRB_AGT_ADR 0x08
+
+/* Hub 4 */
+#define UNM_HW_PEGN0_CRB_AGT_ADR 0x40
+#define UNM_HW_PEGN1_CRB_AGT_ADR 0x41
+#define UNM_HW_PEGN2_CRB_AGT_ADR 0x42
+#define UNM_HW_PEGN3_CRB_AGT_ADR 0x43
+#define UNM_HW_PEGNI_CRB_AGT_ADR 0x44
+#define UNM_HW_PEGND_CRB_AGT_ADR 0x45
+#define UNM_HW_PEGNC_CRB_AGT_ADR 0x46
+#define UNM_HW_PEGR0_CRB_AGT_ADR 0x47
+#define UNM_HW_PEGR1_CRB_AGT_ADR 0x48
+#define UNM_HW_PEGR2_CRB_AGT_ADR 0x49
+#define UNM_HW_PEGR3_CRB_AGT_ADR 0x4a
+#define UNM_HW_PEGN4_CRB_AGT_ADR 0x4b
+
+/* Hub 5 */
+#define UNM_HW_PEGS0_CRB_AGT_ADR 0x40
+#define UNM_HW_PEGS1_CRB_AGT_ADR 0x41
+#define UNM_HW_PEGS2_CRB_AGT_ADR 0x42
+#define UNM_HW_PEGS3_CRB_AGT_ADR 0x43
+#define UNM_HW_PEGSI_CRB_AGT_ADR 0x44
+#define UNM_HW_PEGSD_CRB_AGT_ADR 0x45
+#define UNM_HW_PEGSC_CRB_AGT_ADR 0x46
+
+/* Hub 6 */
+#define UNM_HW_CAS0_CRB_AGT_ADR 0x46
+#define UNM_HW_CAS1_CRB_AGT_ADR 0x47
+#define UNM_HW_CAS2_CRB_AGT_ADR 0x48
+#define UNM_HW_CAS3_CRB_AGT_ADR 0x49
+#define UNM_HW_NCM_CRB_AGT_ADR 0x16
+#define UNM_HW_TMR_CRB_AGT_ADR 0x17
+#define UNM_HW_XDMA_CRB_AGT_ADR 0x05
+#define UNM_HW_OCM0_CRB_AGT_ADR 0x06
+#define UNM_HW_OCM1_CRB_AGT_ADR 0x07
+
+/* This field defines PCI/X adr [25:20] of agents on the CRB */
+/* */
+#define UNM_HW_PX_MAP_CRB_PH 0
+#define UNM_HW_PX_MAP_CRB_PS 1
+#define UNM_HW_PX_MAP_CRB_MN 2
+#define UNM_HW_PX_MAP_CRB_MS 3
+#define UNM_HW_PX_MAP_CRB_SRE 5
+#define UNM_HW_PX_MAP_CRB_NIU 6
+#define UNM_HW_PX_MAP_CRB_QMN 7
+#define UNM_HW_PX_MAP_CRB_SQN0 8
+#define UNM_HW_PX_MAP_CRB_SQN1 9
+#define UNM_HW_PX_MAP_CRB_SQN2 10
+#define UNM_HW_PX_MAP_CRB_SQN3 11
+#define UNM_HW_PX_MAP_CRB_QMS 12
+#define UNM_HW_PX_MAP_CRB_SQS0 13
+#define UNM_HW_PX_MAP_CRB_SQS1 14
+#define UNM_HW_PX_MAP_CRB_SQS2 15
+#define UNM_HW_PX_MAP_CRB_SQS3 16
+#define UNM_HW_PX_MAP_CRB_PGN0 17
+#define UNM_HW_PX_MAP_CRB_PGN1 18
+#define UNM_HW_PX_MAP_CRB_PGN2 19
+#define UNM_HW_PX_MAP_CRB_PGN3 20
+#define UNM_HW_PX_MAP_CRB_PGND 21
+#define UNM_HW_PX_MAP_CRB_PGNI 22
+#define UNM_HW_PX_MAP_CRB_PGS0 23
+#define UNM_HW_PX_MAP_CRB_PGS1 24
+#define UNM_HW_PX_MAP_CRB_PGS2 25
+#define UNM_HW_PX_MAP_CRB_PGS3 26
+#define UNM_HW_PX_MAP_CRB_PGSD 27
+#define UNM_HW_PX_MAP_CRB_PGSI 28
+#define UNM_HW_PX_MAP_CRB_SN 29
+#define UNM_HW_PX_MAP_CRB_EG 31
+#define UNM_HW_PX_MAP_CRB_PH2 32
+#define UNM_HW_PX_MAP_CRB_PS2 33
+#define UNM_HW_PX_MAP_CRB_CAM 34
+#define UNM_HW_PX_MAP_CRB_CAS0 35
+#define UNM_HW_PX_MAP_CRB_CAS1 36
+#define UNM_HW_PX_MAP_CRB_CAS2 37
+#define UNM_HW_PX_MAP_CRB_C2C0 38
+#define UNM_HW_PX_MAP_CRB_C2C1 39
+#define UNM_HW_PX_MAP_CRB_TIMR 40
+/* N/A: Not use in either Phantom1 or Phantom2 => use for TIMR */
+/* #define PX_MAP_CRB_C2C2 40 */
+/* #define PX_MAP_CRB_SS 41 */
+#define UNM_HW_PX_MAP_CRB_RPMX1 42
+#define UNM_HW_PX_MAP_CRB_RPMX2 43
+#define UNM_HW_PX_MAP_CRB_RPMX3 44
+#define UNM_HW_PX_MAP_CRB_RPMX4 45
+#define UNM_HW_PX_MAP_CRB_RPMX5 46
+#define UNM_HW_PX_MAP_CRB_RPMX6 47
+#define UNM_HW_PX_MAP_CRB_RPMX7 48
+#define UNM_HW_PX_MAP_CRB_XDMA 49
+#define UNM_HW_PX_MAP_CRB_I2Q 50
+#define UNM_HW_PX_MAP_CRB_ROMUSB 51
+#define UNM_HW_PX_MAP_CRB_CAS3 52
+#define UNM_HW_PX_MAP_CRB_RPMX0 53
+#define UNM_HW_PX_MAP_CRB_RPMX8 54
+#define UNM_HW_PX_MAP_CRB_RPMX9 55
+#define UNM_HW_PX_MAP_CRB_OCM0 56
+#define UNM_HW_PX_MAP_CRB_OCM1 57
+#define UNM_HW_PX_MAP_CRB_SMB 58
+#define UNM_HW_PX_MAP_CRB_I2C0 59
+#define UNM_HW_PX_MAP_CRB_I2C1 60
+#define UNM_HW_PX_MAP_CRB_LPC 61
+#define UNM_HW_PX_MAP_CRB_PGNC 62
+#define UNM_HW_PX_MAP_CRB_PGR0 63
+#define UNM_HW_PX_MAP_CRB_PGR1 4
+#define UNM_HW_PX_MAP_CRB_PGR2 30
+#define UNM_HW_PX_MAP_CRB_PGR3 41
+
+/* This field defines CRB adr [31:20] of the agents */
+/* */
+
+#define UNM_HW_CRB_HUB_AGT_ADR_MN ((UNM_HW_H0_CH_HUB_ADR << 7) \
+ | UNM_HW_MN_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PH ((UNM_HW_H0_CH_HUB_ADR << 7) \
+ | UNM_HW_PH_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_MS ((UNM_HW_H0_CH_HUB_ADR << 7) \
+ | UNM_HW_MS_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_PS ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_PS_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SS ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SS_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX3 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX3_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_QMS ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_QMS_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQS0 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SQGS0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQS1 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SQGS1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQS2 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SQGS2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQS3 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SQGS3_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_C2C0 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_C2C0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_C2C1 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_C2C1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX2 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX4 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX4_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX7 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX7_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX9 ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX9_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SMB ((UNM_HW_H1_CH_HUB_ADR << 7) \
+ | UNM_HW_SMB_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_NIU ((UNM_HW_H2_CH_HUB_ADR << 7) \
+ | UNM_HW_NIU_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_I2C0 ((UNM_HW_H2_CH_HUB_ADR << 7) \
+ | UNM_HW_I2C0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_I2C1 ((UNM_HW_H2_CH_HUB_ADR << 7) \
+ | UNM_HW_I2C1_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_SRE ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_SRE_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_EG ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_EG_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX0 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_QMN ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_QM_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQN0 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_SQG0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQN1 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_SQG1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQN2 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_SQG2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SQN3 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_SQG3_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX1 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX5 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX5_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX6 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX6_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_RPMX8 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_RPMX8_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_CAS0 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_CAS0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_CAS1 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_CAS1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_CAS2 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_CAS2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_CAS3 ((UNM_HW_H3_CH_HUB_ADR << 7) \
+ | UNM_HW_CAS3_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_PGNI ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGNI_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGND ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGND_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGN0 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGN0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGN1 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGN1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGN2 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGN2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGN3 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGN3_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGN4 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGN4_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_PGNC ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGNC_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGR0 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGR0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGR1 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGR1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGR2 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGR2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGR3 ((UNM_HW_H4_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGR3_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_PGSI ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGSI_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGSD ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGSD_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGS0 ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGS0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGS1 ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGS1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGS2 ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGS2_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGS3 ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGS3_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_PGSC ((UNM_HW_H5_CH_HUB_ADR << 7) \
+ | UNM_HW_PEGSC_CRB_AGT_ADR)
+
+#define UNM_HW_CRB_HUB_AGT_ADR_CAM ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_NCM_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_TIMR ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_TMR_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_XDMA ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_XDMA_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_SN ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_SN_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_I2Q ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_I2Q_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_ROMUSB ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_ROMUSB_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_OCM0 ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_OCM0_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_OCM1 ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_OCM1_CRB_AGT_ADR)
+#define UNM_HW_CRB_HUB_AGT_ADR_LPC ((UNM_HW_H6_CH_HUB_ADR << 7) \
+ | UNM_HW_LPC_CRB_AGT_ADR)
+
+/*
+ * ROM USB CRB space is divided into 4 regions depending on decode of
+ * address bits [19:16]
+ */
+#define ROMUSB_GLB (UNM_CRB_ROMUSB + 0x00000)
+#define ROMUSB_ROM (UNM_CRB_ROMUSB + 0x10000)
+#define ROMUSB_USB (UNM_CRB_ROMUSB + 0x20000)
+#define ROMUSB_DIRECT_ROM (UNM_CRB_ROMUSB + 0x30000)
+#define ROMUSB_TAP (UNM_CRB_ROMUSB + 0x40000)
+
+/* ROMUSB GLB register definitions */
+#define UNM_ROMUSB_GLB_CONTROL (ROMUSB_GLB + 0x0000)
+#define UNM_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004)
+#define UNM_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008)
+#define UNM_ROMUSB_GLB_PAD_GPIO_I (ROMUSB_GLB + 0x000c)
+#define UNM_ROMUSB_GLB_RNG_PLL_CTL (ROMUSB_GLB + 0x0010)
+#define UNM_ROMUSB_GLB_TEST_MUX_O (ROMUSB_GLB + 0x0014)
+#define UNM_ROMUSB_GLB_PLL0_CTRL (ROMUSB_GLB + 0x0018)
+#define UNM_ROMUSB_GLB_PLL1_CTRL (ROMUSB_GLB + 0x001c)
+#define UNM_ROMUSB_GLB_PLL2_CTRL (ROMUSB_GLB + 0x0020)
+#define UNM_ROMUSB_GLB_PLL3_CTRL (ROMUSB_GLB + 0x0024)
+#define UNM_ROMUSB_GLB_PLL_LOCK (ROMUSB_GLB + 0x0028)
+#define UNM_ROMUSB_GLB_EXTERN_INT (ROMUSB_GLB + 0x002c)
+#define UNM_ROMUSB_GLB_PH_RST (ROMUSB_GLB + 0x0030)
+#define UNM_ROMUSB_GLB_PS_RST (ROMUSB_GLB + 0x0034)
+#define UNM_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038)
+#define UNM_ROMUSB_GLB_MIU_RST (ROMUSB_GLB + 0x003c)
+#define UNM_ROMUSB_GLB_CRB_RST (ROMUSB_GLB + 0x0040)
+#define UNM_ROMUSB_GLB_TEST_MUX_SEL (ROMUSB_GLB + 0x0044)
+#define UNM_ROMUSB_GLB_MN_COM_A2T (ROMUSB_GLB + 0x0050)
+#define UNM_ROMUSB_GLB_REV_ID (ROMUSB_GLB + 0x0054)
+#define UNM_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c)
+#define UNM_ROMUSB_GLB_VENDOR_DEV_ID (ROMUSB_GLB + 0x0058)
+#define UNM_ROMUSB_GLB_CHIP_CLK_CTRL (ROMUSB_GLB + 0x00a8)
+
+#define UNM_ROMUSB_GPIO(n) ((n) <= 15 ? (ROMUSB_GLB + 0x60 + (4 * (n))): \
+ ((n) <= 18)?(ROMUSB_GLB + 0x70 + (4 * (n))): \
+ (ROMUSB_GLB + 0x70 + (4 * (19))))
+
+#define UNM_ROMUSB_ROM_CONTROL (ROMUSB_ROM + 0x0000)
+#define UNM_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004)
+#define UNM_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008)
+#define UNM_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c)
+#define UNM_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010)
+#define UNM_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014)
+#define UNM_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018)
+#define UNM_ROMUSB_ROM_AGT_TAG (ROMUSB_ROM + 0x001c)
+#define UNM_ROMUSB_ROM_TIME_PARM (ROMUSB_ROM + 0x0020)
+#define UNM_ROMUSB_ROM_CLK_DIV (ROMUSB_ROM + 0x0024)
+#define UNM_ROMUSB_ROM_MISS_INSTR (ROMUSB_ROM + 0x0028)
+
+/* Lock IDs for ROM lock */
+#define ROM_LOCK_DRIVER 0x0d417340
+
+/* Lock IDs for PHY lock */
+#define PHY_LOCK_DRIVER 0x44524956
+
+#define UNM_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */
+#define UNM_PCI_CRB_WINDOW(A) (UNM_PCI_CRBSPACE + (A)*UNM_PCI_CRB_WINDOWSIZE)
+#define UNM_CRB_C2C_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_C2C0)
+#define UNM_CRB_C2C_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_C2C1)
+#define UNM_CRB_C2C_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_C2C2)
+#define UNM_CRB_CAM UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_CAM)
+#define UNM_CRB_CASPER UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_CAS)
+#define UNM_CRB_CASPER_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_CAS0)
+#define UNM_CRB_CASPER_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_CAS1)
+#define UNM_CRB_CASPER_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_CAS2)
+#define UNM_CRB_DDR_MD UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_MS)
+#define UNM_CRB_DDR_NET UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_MN)
+#define UNM_CRB_EPG UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_EG)
+#define UNM_CRB_I2Q UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_I2Q)
+#define UNM_CRB_NIU UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_NIU)
+/* HACK upon HACK upon HACK (for PCIE builds) */
+#define UNM_CRB_PCIX_HOST UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PH)
+#define UNM_CRB_PCIX_HOST2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PH2)
+#define UNM_CRB_PCIX_MD UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PS)
+#define UNM_CRB_PCIE UNM_CRB_PCIX_MD
+// window 1 pcie slot
+#define UNM_CRB_PCIE2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PS2)
+
+#define UNM_CRB_PEG_MD_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGS0)
+#define UNM_CRB_PEG_MD_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGS1)
+#define UNM_CRB_PEG_MD_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGS2)
+#define UNM_CRB_PEG_MD_3 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGS3)
+#define UNM_CRB_PEG_MD_D UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGSD)
+#define UNM_CRB_PEG_MD_I UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGSI)
+#define UNM_CRB_PEG_NET_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGN0)
+#define UNM_CRB_PEG_NET_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGN1)
+#define UNM_CRB_PEG_NET_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGN2)
+#define UNM_CRB_PEG_NET_3 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGN3)
+#define UNM_CRB_PEG_NET_D UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGND)
+#define UNM_CRB_PEG_NET_I UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_PGNI)
+#define UNM_CRB_PQM_MD UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_QMS)
+#define UNM_CRB_PQM_NET UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_QMN)
+#define UNM_CRB_QDR_MD UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SS)
+#define UNM_CRB_QDR_NET UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SN)
+#define UNM_CRB_ROMUSB UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_ROMUSB)
+#define UNM_CRB_RPMX_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX0)
+#define UNM_CRB_RPMX_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX1)
+#define UNM_CRB_RPMX_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX2)
+#define UNM_CRB_RPMX_3 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX3)
+#define UNM_CRB_RPMX_4 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX4)
+#define UNM_CRB_RPMX_5 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX5)
+#define UNM_CRB_RPMX_6 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX6)
+#define UNM_CRB_RPMX_7 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_RPMX7)
+#define UNM_CRB_SQM_MD_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQS0)
+#define UNM_CRB_SQM_MD_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQS1)
+#define UNM_CRB_SQM_MD_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQS2)
+#define UNM_CRB_SQM_MD_3 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQS3)
+#define UNM_CRB_SQM_NET_0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQN0)
+#define UNM_CRB_SQM_NET_1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQN1)
+#define UNM_CRB_SQM_NET_2 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQN2)
+#define UNM_CRB_SQM_NET_3 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SQN3)
+#define UNM_CRB_SRE UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SRE)
+#define UNM_CRB_TIMER UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_TIMR)
+#define UNM_CRB_XDMA UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_XDMA)
+#define UNM_CRB_I2C0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_I2C0)
+#define UNM_CRB_I2C1 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_I2C1)
+#define UNM_CRB_OCM0 UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_OCM0)
+#define UNM_CRB_SMB UNM_PCI_CRB_WINDOW(UNM_HW_PX_MAP_CRB_SMB)
+
+#define UNM_CRB_MAX UNM_PCI_CRB_WINDOW(64)
+
+/*
+ * ====================== BASE ADDRESSES ON-CHIP ======================
+ * Base addresses of major components on-chip.
+ * ====================== BASE ADDRESSES ON-CHIP ======================
+ */
+#define UNM_ADDR_DDR_NET (0x0000000000000000ULL)
+#define UNM_ADDR_DDR_NET_MAX (0x000000000fffffffULL)
+
+/*
+ * Imbus address bit used to indicate a host address. This bit is
+ * eliminated by the pcie bar and bar select before presentation
+ * over pcie.
+ */
+/* host memory via IMBUS */
+#define NX_P2_ADDR_PCIE (0x0000000800000000ULL)
+#define NX_P3_ADDR_PCIE (0x0000008000000000ULL)
+
+#define UNM_ADDR_PCIE_MAX (0x0000000FFFFFFFFFULL)
+#define UNM_ADDR_OCM0 (0x0000000200000000ULL)
+#define UNM_ADDR_OCM0_MAX (0x00000002000fffffULL)
+#define UNM_ADDR_OCM1 (0x0000000200400000ULL)
+#define UNM_ADDR_OCM1_MAX (0x00000002004fffffULL)
+#define UNM_ADDR_QDR_NET (0x0000000300000000ULL)
+
+#define NX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL)
+#define NX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL)
+/*
+ * The ifdef at the bottom should go. All drivers should start using the
+ * above 2 defines.
+ */
+#ifdef P3
+#define UNM_ADDR_QDR_NET_MAX NX_P3_ADDR_QDR_NET_MAX
+#else
+#define UNM_ADDR_QDR_NET_MAX NX_P2_ADDR_QDR_NET_MAX
+#endif
+
+#define D3_CRB_REG_FUN0 (UNM_PCIX_PS_REG(0x0084))
+#define D3_CRB_REG_FUN1 (UNM_PCIX_PS_REG(0x1084))
+#define D3_CRB_REG_FUN2 (UNM_PCIX_PS_REG(0x2084))
+#define D3_CRB_REG_FUN3 (UNM_PCIX_PS_REG(0x3084))
+
+
+#define ISR_I2Q_CLR_PCI_LO (UNM_PCIX_PS_REG(UNM_I2Q_CLR_PCI_LO))
+#define ISR_I2Q_CLR_PCI_HI (UNM_PCIX_PS_REG(UNM_I2Q_CLR_PCI_HI))
+#define UNM_PCI_ARCH_CRB_BASE (UNM_PCI_DIRECT_CRB)
+
+/* we're mapping 128MB of mem on the PCI bus */
+#define UNM_PCI_MAPSIZE 128
+#define UNM_PCI_DDR_NET (unsigned long)0x00000000
+#define UNM_PCI_DDR_NET_MAX (unsigned long)0x01ffffff
+#define UNM_PCI_DDR_MD (unsigned long)0x02000000
+#define UNM_PCI_DDR_MD_MAX (unsigned long)0x03ffffff
+#define UNM_PCI_QDR_NET (unsigned long)0x04000000
+#define UNM_PCI_QDR_NET_MAX (unsigned long)0x043fffff
+#define UNM_PCI_DIRECT_CRB (unsigned long)0x04400000
+#define UNM_PCI_DIRECT_CRB_MAX (unsigned long)0x047fffff
+#define UNM_PCI_CAMQM (unsigned long)0x04800000
+#define UNM_PCI_CAMQM_MAX (unsigned long)0x04ffffff
+#define UNM_PCI_OCM0 (unsigned long)0x05000000
+#define UNM_PCI_OCM0_MAX (unsigned long)0x050fffff
+#define UNM_PCI_OCM1 (unsigned long)0x05100000
+#define UNM_PCI_OCM1_MAX (unsigned long)0x051fffff
+#define UNM_PCI_CRBSPACE (unsigned long)0x06000000
+#define UNM_PCI_CRBSPACE_MAX (unsigned long)0x07ffffff
+#define UNM_PCI_128MB_SIZE (unsigned long)0x08000000
+#define UNM_PCI_32MB_SIZE (unsigned long)0x02000000
+#define UNM_PCI_2MB_SIZE (unsigned long)0x00200000
+
+/*
+ * The basic unit of access when reading/writing control registers.
+ */
+typedef long native_t; /* most efficient integer on h/w */
+typedef __uint64_t unm_dataword_t; /* single word in data space */
+typedef __uint64_t unm64ptr_t; /* a pointer that occupies 64 bits */
+#define UNM64PTR(P) ((unm64ptr_t)((native_t)(P))) /* convert for us */
+
+typedef __uint32_t unm_crbword_t; /* single word in CRB space */
+
+/*
+ * Definitions relating to access/control of the Network Interface Unit
+ * h/w block.
+ */
+/*
+ * Configuration registers.
+ */
+#define UNM_NIU_MODE (UNM_CRB_NIU + 0x00000)
+
+#define UNM_NIU_XG_SINGLE_TERM (UNM_CRB_NIU + 0x00004)
+#define UNM_NIU_XG_DRIVE_HI (UNM_CRB_NIU + 0x00008)
+#define UNM_NIU_XG_DRIVE_LO (UNM_CRB_NIU + 0x0000c)
+#define UNM_NIU_XG_DTX (UNM_CRB_NIU + 0x00010)
+#define UNM_NIU_XG_DEQ (UNM_CRB_NIU + 0x00014)
+#define UNM_NIU_XG_WORD_ALIGN (UNM_CRB_NIU + 0x00018)
+#define UNM_NIU_XG_RESET (UNM_CRB_NIU + 0x0001c)
+#define UNM_NIU_XG_POWER_DOWN (UNM_CRB_NIU + 0x00020)
+#define UNM_NIU_XG_RESET_PLL (UNM_CRB_NIU + 0x00024)
+#define UNM_NIU_XG_SERDES_LOOPBACK (UNM_CRB_NIU + 0x00028)
+#define UNM_NIU_XG_DO_BYTE_ALIGN (UNM_CRB_NIU + 0x0002c)
+#define UNM_NIU_XG_TX_ENABLE (UNM_CRB_NIU + 0x00030)
+#define UNM_NIU_XG_RX_ENABLE (UNM_CRB_NIU + 0x00034)
+#define UNM_NIU_XG_STATUS (UNM_CRB_NIU + 0x00038)
+#define UNM_NIU_XG_PAUSE_THRESHOLD (UNM_CRB_NIU + 0x0003c)
+#define UNM_NIU_INT_MASK (UNM_CRB_NIU + 0x00040)
+#define UNM_NIU_ACTIVE_INT (UNM_CRB_NIU + 0x00044)
+#define UNM_NIU_MASKABLE_INT (UNM_CRB_NIU + 0x00048)
+#define UNM_NIU_TEST_MUX_CTL (UNM_CRB_NIU + 0x00094)
+#define UNM_NIU_XG_PAUSE_CTL (UNM_CRB_NIU + 0x00098)
+#define UNM_NIU_XG_PAUSE_LEVEL (UNM_CRB_NIU + 0x000dc)
+#define UNM_NIU_XG_SEL (UNM_CRB_NIU + 0x00128)
+#define UNM_NIU_GB_PAUSE_CTL (UNM_CRB_NIU + 0x0030c)
+#define UNM_NIU_FULL_LEVEL_XG (UNM_CRB_NIU + 0x00450)
+
+
+#define UNM_NIU_XG1_RESET (UNM_CRB_NIU + 0x0011c)
+#define UNM_NIU_XG1_POWER_DOWN (UNM_CRB_NIU + 0x00120)
+#define UNM_NIU_XG1_RESET_PLL (UNM_CRB_NIU + 0x00124)
+
+#define UNM_NIU_STRAP_VALUE_SAVE_HIGHER (UNM_CRB_NIU + 0x0004c)
+
+#define UNM_NIU_GB_SERDES_RESET (UNM_CRB_NIU + 0x00050)
+#define UNM_NIU_GB0_GMII_MODE (UNM_CRB_NIU + 0x00054)
+#define UNM_NIU_GB0_MII_MODE (UNM_CRB_NIU + 0x00058)
+#define UNM_NIU_GB1_GMII_MODE (UNM_CRB_NIU + 0x0005c)
+#define UNM_NIU_GB1_MII_MODE (UNM_CRB_NIU + 0x00060)
+#define UNM_NIU_GB2_GMII_MODE (UNM_CRB_NIU + 0x00064)
+#define UNM_NIU_GB2_MII_MODE (UNM_CRB_NIU + 0x00068)
+#define UNM_NIU_GB3_GMII_MODE (UNM_CRB_NIU + 0x0006c)
+#define UNM_NIU_GB3_MII_MODE (UNM_CRB_NIU + 0x00070)
+#define UNM_NIU_REMOTE_LOOPBACK (UNM_CRB_NIU + 0x00074)
+#define UNM_NIU_GB0_HALF_DUPLEX (UNM_CRB_NIU + 0x00078)
+#define UNM_NIU_GB1_HALF_DUPLEX (UNM_CRB_NIU + 0x0007c)
+#define UNM_NIU_GB2_HALF_DUPLEX (UNM_CRB_NIU + 0x00080)
+#define UNM_NIU_GB3_HALF_DUPLEX (UNM_CRB_NIU + 0x00084)
+#define UNM_NIU_RESET_SYS_FIFOS (UNM_CRB_NIU + 0x00088)
+#define UNM_NIU_GB_CRC_DROP (UNM_CRB_NIU + 0x0008c)
+#define UNM_NIU_GB_DROP_WRONGADDR (UNM_CRB_NIU + 0x00090)
+#define UNM_NIU_TEST_MUX_CTL (UNM_CRB_NIU + 0x00094)
+#define UNM_NIU_XG_PAUSE_CTL (UNM_CRB_NIU + 0x00098)
+#define UNM_NIU_GB0_PAUSE_LEVEL (UNM_CRB_NIU + 0x000cc)
+#define UNM_NIU_GB1_PAUSE_LEVEL (UNM_CRB_NIU + 0x000d0)
+#define UNM_NIU_GB2_PAUSE_LEVEL (UNM_CRB_NIU + 0x000d4)
+#define UNM_NIU_GB3_PAUSE_LEVEL (UNM_CRB_NIU + 0x000d8)
+#define UNM_NIU_XG_PAUSE_LEVEL (UNM_CRB_NIU + 0x000dc)
+#define UNM_NIU_FRAME_COUNT_SELECT (UNM_CRB_NIU + 0x000ac)
+#define UNM_NIU_FRAME_COUNT (UNM_CRB_NIU + 0x000b0)
+#define UNM_NIU_XG_SE (UNM_CRB_NIU + 0x00128)
+#define UNM_NIU_FULL_LEVEL_XG (UNM_CRB_NIU + 0x00450)
+
+#define UNM_NIU_FC_RX_STATUS(I) (UNM_CRB_NIU + 0x10000 + (I)*0x10000)
+#define UNM_NIU_FC_RX_COMMA_DETECT(I) (UNM_CRB_NIU + 0x10004 + (I)*0x10000)
+#define UNM_NIU_FC_LASER_UNSAFE(I) (UNM_CRB_NIU + 0x10008 + (I)*0x10000)
+#define UNM_NIU_FC_TX_CONTROL(I) (UNM_CRB_NIU + 0x1000c + (I)*0x10000)
+#define UNM_NIU_FC_ON_OFFLINE_CTL(I) (UNM_CRB_NIU + 0x10010 + (I)*0x10000)
+#define UNM_NIU_FC_PORT_ACTIVE_STAT(I) (UNM_CRB_NIU + 0x10014 + (I)*0x10000)
+#define UNM_NIU_FC_PORT_INACTIVE_STAT(I)(UNM_CRB_NIU + 0x10018 + (I)*0x10000)
+#define UNM_NIU_FC_LINK_FAILURE_CNT(I) (UNM_CRB_NIU + 0x1001c + (I)*0x10000)
+#define UNM_NIU_FC_LOSS_SYNC_CNT(I) (UNM_CRB_NIU + 0x10020 + (I)*0x10000)
+#define UNM_NIU_FC_LOSS_SIGNAL_CNT(I) (UNM_CRB_NIU + 0x10024 + (I)*0x10000)
+#define UNM_NIU_FC_PRIM_SEQ_ERR_CNT(I) (UNM_CRB_NIU + 0x10028 + (I)*0x10000)
+#define UNM_NIU_FC_INVLD_TX_WORD_CNT(I) (UNM_CRB_NIU + 0x1002c + (I)*0x10000)
+#define UNM_NIU_FC_INVLD_CRC_CNT(I) (UNM_CRB_NIU + 0x10030 + (I)*0x10000)
+#define UNM_NIU_FC_RX_CELL_CNT(I) (UNM_CRB_NIU + 0x10034 + (I)*0x10000)
+#define UNM_NIU_FC_TX_CELL_CNT(I) (UNM_CRB_NIU + 0x10038 + (I)*0x10000)
+#define UNM_NIU_FC_B2B_CREDIT(I) (UNM_CRB_NIU + 0x1003c + (I)*0x10000)
+#define UNM_NIU_FC_LOGIN_DONE(I) (UNM_CRB_NIU + 0x10040 + (I)*0x10000)
+#define UNM_NIU_FC_OPERATING_SPEED(I) (UNM_CRB_NIU + 0x10044 + (I)*0x10000)
+
+#define UNM_NIU_GB_MAC_CONFIG_0(I) (UNM_CRB_NIU + 0x30000 + (I)*0x10000)
+#define UNM_NIU_GB_MAC_CONFIG_1(I) (UNM_CRB_NIU + 0x30004 + (I)*0x10000)
+#define UNM_NIU_GB_MAC_IPG_IFG(I) (UNM_CRB_NIU + 0x30008 + (I)*0x10000)
+#define UNM_NIU_GB_HALF_DUPLEX_CTRL(I) (UNM_CRB_NIU + 0x3000c + (I)*0x10000)
+#define UNM_NIU_GB_MAX_FRAME_SIZE(I) (UNM_CRB_NIU + 0x30010 + (I)*0x10000)
+#define UNM_NIU_GB_TEST_REG(I) (UNM_CRB_NIU + 0x3001c + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_CONFIG(I) (UNM_CRB_NIU + 0x30020 + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_COMMAND(I) (UNM_CRB_NIU + 0x30024 + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_ADDR(I) (UNM_CRB_NIU + 0x30028 + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_CTRL(I) (UNM_CRB_NIU + 0x3002c + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_STATUS(I) (UNM_CRB_NIU + 0x30030 + (I)*0x10000)
+#define UNM_NIU_GB_MII_MGMT_INDICATE(I) (UNM_CRB_NIU + 0x30034 + (I)*0x10000)
+#define UNM_NIU_GB_INTERFACE_CTRL(I) (UNM_CRB_NIU + 0x30038 + (I)*0x10000)
+#define UNM_NIU_GB_INTERFACE_STATUS(I) (UNM_CRB_NIU + 0x3003c + (I)*0x10000)
+#define UNM_NIU_GB_STATION_ADDR_0(I) (UNM_CRB_NIU + 0x30040 + (I)*0x10000)
+#define UNM_NIU_GB_STATION_ADDR_1(I) (UNM_CRB_NIU + 0x30044 + (I)*0x10000)
+
+#define UNM_NIU_XGE_CONFIG_0 (UNM_CRB_NIU + 0x70000)
+#define UNM_NIU_XGE_CONFIG_1 (UNM_CRB_NIU + 0x70004)
+#define UNM_NIU_XGE_IPG (UNM_CRB_NIU + 0x70008)
+#define UNM_NIU_XGE_STATION_ADDR_0_HI (UNM_CRB_NIU + 0x7000c)
+#define UNM_NIU_XGE_STATION_ADDR_0_1 (UNM_CRB_NIU + 0x70010)
+#define UNM_NIU_XGE_STATION_ADDR_1_LO (UNM_CRB_NIU + 0x70014)
+#define UNM_NIU_XGE_STATUS (UNM_CRB_NIU + 0x70018)
+#define UNM_NIU_XGE_MAX_FRAME_SIZE (UNM_CRB_NIU + 0x7001c)
+#define UNM_NIU_XGE_PAUSE_FRAME_VALUE (UNM_CRB_NIU + 0x70020)
+#define UNM_NIU_XGE_TX_BYTE_CNT (UNM_CRB_NIU + 0x70024)
+#define UNM_NIU_XGE_TX_FRAME_CNT (UNM_CRB_NIU + 0x70028)
+#define UNM_NIU_XGE_RX_BYTE_CNT (UNM_CRB_NIU + 0x7002c)
+#define UNM_NIU_XGE_RX_FRAME_CNT (UNM_CRB_NIU + 0x70030)
+#define UNM_NIU_XGE_AGGR_ERROR_CNT (UNM_CRB_NIU + 0x70034)
+#define UNM_NIU_XGE_MULTICAST_FRAME_CNT (UNM_CRB_NIU + 0x70038)
+#define UNM_NIU_XGE_UNICAST_FRAME_CNT (UNM_CRB_NIU + 0x7003c)
+#define UNM_NIU_XGE_CRC_ERROR_CNT (UNM_CRB_NIU + 0x70040)
+#define UNM_NIU_XGE_OVERSIZE_FRAME_ERR (UNM_CRB_NIU + 0x70044)
+#define UNM_NIU_XGE_UNDERSIZE_FRAME_ERR (UNM_CRB_NIU + 0x70048)
+#define UNM_NIU_XGE_LOCAL_ERROR_CNT (UNM_CRB_NIU + 0x7004c)
+#define UNM_NIU_XGE_REMOTE_ERROR_CNT (UNM_CRB_NIU + 0x70050)
+#define UNM_NIU_XGE_CONTROL_CHAR_CNT (UNM_CRB_NIU + 0x70054)
+#define UNM_NIU_XGE_PAUSE_FRAME_CNT (UNM_CRB_NIU + 0x70058)
+#define UNM_NIU_XG1_CONFIG_0 (UNM_CRB_NIU + 0x80000)
+#define UNM_NIU_XG1_CONFIG_1 (UNM_CRB_NIU + 0x80004)
+#define UNM_NIU_XG1_IPG (UNM_CRB_NIU + 0x80008)
+#define UNM_NIU_XG1_STATION_ADDR_0_HI (UNM_CRB_NIU + 0x8000c)
+#define UNM_NIU_XG1_STATION_ADDR_0_1 (UNM_CRB_NIU + 0x80010)
+#define UNM_NIU_XG1_STATION_ADDR_1_LO (UNM_CRB_NIU + 0x80014)
+#define UNM_NIU_XG1_STATUS (UNM_CRB_NIU + 0x80018)
+#define UNM_NIU_XG1_MAX_FRAME_SIZE (UNM_CRB_NIU + 0x8001c)
+#define UNM_NIU_XG1_PAUSE_FRAME_VALUE (UNM_CRB_NIU + 0x80020)
+#define UNM_NIU_XG1_TX_BYTE_CNT (UNM_CRB_NIU + 0x80024)
+#define UNM_NIU_XG1_TX_FRAME_CNT (UNM_CRB_NIU + 0x80028)
+#define UNM_NIU_XG1_RX_BYTE_CNT (UNM_CRB_NIU + 0x8002c)
+#define UNM_NIU_XG1_RX_FRAME_CNT (UNM_CRB_NIU + 0x80030)
+#define UNM_NIU_XG1_AGGR_ERROR_CNT (UNM_CRB_NIU + 0x80034)
+#define UNM_NIU_XG1_MULTICAST_FRAME_CNT (UNM_CRB_NIU + 0x80038)
+#define UNM_NIU_XG1_UNICAST_FRAME_CNT (UNM_CRB_NIU + 0x8003c)
+#define UNM_NIU_XG1_CRC_ERROR_CNT (UNM_CRB_NIU + 0x80040)
+#define UNM_NIU_XG1_OVERSIZE_FRAME_ERR (UNM_CRB_NIU + 0x80044)
+#define UNM_NIU_XG1_UNDERSIZE_FRAME_ERR (UNM_CRB_NIU + 0x80048)
+#define UNM_NIU_XG1_LOCAL_ERROR_CNT (UNM_CRB_NIU + 0x8004c)
+#define UNM_NIU_XG1_REMOTE_ERROR_CNT (UNM_CRB_NIU + 0x80050)
+#define UNM_NIU_XG1_CONTROL_CHAR_CNT (UNM_CRB_NIU + 0x80054)
+#define UNM_NIU_XG1_PAUSE_FRAME_CNT (UNM_CRB_NIU + 0x80058)
+
+#define UNM_TIMER_GT_TICKCTL (UNM_CRB_TIMER + 0x00200)
+#define UNM_TIMER_GLOBAL_TIMESTAMP_LO (UNM_CRB_TIMER + 0x00220)
+#define UNM_TIMER_TIMESTAMP (UNM_CRB_TIMER + 0x00208)
+
+#define UNM_PEXQ_REQ_HDR_LO (UNM_CRB_XDMA + 0x00110)
+#define UNM_PEXQ_REQ_HDR_HI (UNM_CRB_XDMA + 0x00114)
+
+/* P3 802.3ap */
+#define UNM_NIU_AP_MAC_CONFIG_0(I) (UNM_CRB_NIU + 0xa0000 + (I)*0x10000)
+#define UNM_NIU_AP_MAC_CONFIG_1(I) (UNM_CRB_NIU + 0xa0004 + (I)*0x10000)
+#define UNM_NIU_AP_MAC_IPG_IFG(I) (UNM_CRB_NIU + 0xa0008 + (I)*0x10000)
+#define UNM_NIU_AP_HALF_DUPLEX_CTRL(I) (UNM_CRB_NIU + 0xa000c + (I)*0x10000)
+#define UNM_NIU_AP_MAX_FRAME_SIZE(I) (UNM_CRB_NIU + 0xa0010 + (I)*0x10000)
+#define UNM_NIU_AP_TEST_REG(I) (UNM_CRB_NIU + 0xa001c + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_CONFIG(I) (UNM_CRB_NIU + 0xa0020 + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_COMMAND(I) (UNM_CRB_NIU + 0xa0024 + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_ADDR(I) (UNM_CRB_NIU + 0xa0028 + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_CTRL(I) (UNM_CRB_NIU + 0xa002c + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_STATUS(I) (UNM_CRB_NIU + 0xa0030 + (I)*0x10000)
+#define UNM_NIU_AP_MII_MGMT_INDICATE(I) (UNM_CRB_NIU + 0xa0034 + (I)*0x10000)
+#define UNM_NIU_AP_INTERFACE_CTRL(I) (UNM_CRB_NIU + 0xa0038 + (I)*0x10000)
+#define UNM_NIU_AP_INTERFACE_STATUS(I) (UNM_CRB_NIU + 0xa003c + (I)*0x10000)
+#define UNM_NIU_AP_STATION_ADDR_0(I) (UNM_CRB_NIU + 0xa0040 + (I)*0x10000)
+#define UNM_NIU_AP_STATION_ADDR_1(I) (UNM_CRB_NIU + 0xa0044 + (I)*0x10000)
+
+/*
+ * Register offsets for MN
+ */
+#define MIU_CONTROL (0x000)
+#define MIU_TAG (0x004)
+#define MIU_TEST_AGT_CTRL (0x090)
+#define MIU_TEST_AGT_ADDR_LO (0x094)
+#define MIU_TEST_AGT_ADDR_HI (0x098)
+#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START 1
+#define MIU_TA_CTL_ENABLE 2
+#define MIU_TA_CTL_WRITE 4
+#define MIU_TA_CTL_BUSY 8
+
+#define SIU_TEST_AGT_CTRL (0x060)
+#define SIU_TEST_AGT_ADDR_LO (0x064)
+#define SIU_TEST_AGT_ADDR_HI (0x078)
+#define SIU_TEST_AGT_WRDATA_LO (0x068)
+#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+#define SIU_TEST_AGT_RDDATA_LO (0x070)
+#define SIU_TEST_AGT_RDDATA_HI (0x074)
+#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
+
+#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
+/* XG Link status */
+#define XG_LINK_UP 0x10
+
+
+/* ====================== Configuration Constants ======================== */
+#define UNM_NIU_PHY_WAITLEN 200000 /* 200ms delay in each loop */
+#define UNM_NIU_PHY_WAITMAX 50 /* 10 seconds before we give up */
+#define UNM_NIU_MAX_GBE_PORTS 4
+#define UNM_NIU_MAX_XG_PORTS 2
+
+typedef __uint8_t unm_ethernet_macaddr_t[6];
+
+#define MIN_CORE_CLK_SPEED 200
+#define MAX_CORE_CLK_SPEED 400
+#define ACCEPTABLE_CORE_CLK_RANGE(speed) \
+ ((speed >= MIN_CORE_CLK_SPEED) && (speed <= MAX_CORE_CLK_SPEED))
+
+#define P2_TICKS_PER_SEC 2048
+#define P2_MIN_TICKS_PER_SEC (P2_TICKS_PER_SEC-10)
+#define P2_MAX_TICKS_PER_SEC (P2_TICKS_PER_SEC+10)
+#define CHECK_TICKS_PER_SEC(ticks) \
+ ((ticks >= P2_MIN_TICKS_PER_SEC) && (ticks <= P2_MAX_TICKS_PER_SEC))
+
+/* ============================= 1GbE =============================== */
+/* Nibble or Byte mode for phy interface (GbE mode only) */
+typedef enum {
+ UNM_NIU_10_100_MB = 0,
+ UNM_NIU_1000_MB
+} unm_niu_gbe_ifmode_t;
+
+/* Promiscous mode options (GbE mode only) */
+typedef enum {
+ UNM_NIU_PROMISCOUS_MODE = 0,
+ UNM_NIU_NON_PROMISCOUS_MODE
+} unm_niu_prom_mode_t;
+
+/*
+ * NIU GB Drop CRC Register
+ */
+typedef struct {
+ unm_crbword_t
+ drop_gb0:1, /* 1:drop pkts with bad CRCs, 0:pass them on */
+ drop_gb1:1, /* 1:drop pkts with bad CRCs, 0:pass them on */
+ drop_gb2:1, /* 1:drop pkts with bad CRCs, 0:pass them on */
+ drop_gb3:1, /* 1:drop pkts with bad CRCs, 0:pass them on */
+ rsvd:28;
+} unm_niu_gb_drop_crc_t;
+
+/*
+ * NIU GB GMII Mode Register (applies to GB0, GB1, GB2, GB3)
+ * To change the mode, turn off the existing mode, then turn on the new mode.
+ */
+typedef struct {
+ unm_crbword_t
+ gmiimode:1, /* 1:GMII mode, 0:xmit clk taken from SERDES */
+ rsvd:29;
+} unm_niu_gb_gmii_mode_t;
+
+/*
+ * NIU GB MII Mode Register (applies to GB0, GB1, GB2, GB3)
+ * To change the mode, turn off the existing mode, then turn on the new mode.
+ */
+typedef struct {
+ unm_crbword_t
+ miimode:1, /* 1:MII mode, 0:xmit clk provided to SERDES */
+ rsvd:29;
+} unm_niu_gb_mii_mode_t;
+
+/*
+ * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3)
+ */
+typedef struct {
+ unm_crbword_t
+ tx_enable:1, /* 1:enable frame xmit, 0:disable */
+ tx_synched:1, /* R/O: xmit enable synched to xmit stream */
+ rx_enable:1, /* 1:enable frame recv, 0:disable */
+ rx_synched:1, /* R/O: recv enable synched to recv stream */
+ tx_flowctl:1, /* 1:enable pause frame generation, 0:disable */
+ rx_flowctl:1, /* 1:act on recv'd pause frames, 0:ignore */
+ rsvd1:2,
+ loopback:1, /* 1:loop MAC xmits to MAC recvs, 0:normal */
+ rsvd2:7,
+ tx_reset_pb:1, /* 1:reset frame xmit protocol blk, 0:no-op */
+ rx_reset_pb:1, /* 1:reset frame recv protocol blk, 0:no-op */
+ tx_reset_mac:1, /* 1:reset data/ctl multiplexer blk, 0:no-op */
+ rx_reset_mac:1, /* 1:reset ctl frames & timers blk, 0:no-op */
+ rsvd3:11,
+ soft_reset:1; /* 1:reset the MAC and the SERDES, 0:no-op */
+} unm_niu_gb_mac_config_0_t;
+
+/*
+ * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3)
+ */
+typedef struct {
+ unm_crbword_t
+ duplex:1, /* 1:full duplex mode, 0:half duplex */
+ crc_enable:1, /* 1:append CRC to xmit frames, 0:dont append */
+ padshort:1, /* 1:pad short frames and add CRC, 0:dont pad */
+ rsvd1:1,
+ checklength:1, /* 1:check framelen with actual, 0:dont check */
+ hugeframes:1, /* 1:allow oversize xmit frames, 0:dont allow */
+ rsvd2:2,
+ intfmode:2, /* 01:nibble (10/100), 10:byte (1000) */
+ rsvd3:2,
+ preamblelen:4, /* preamble field length in bytes, default 7 */
+ rsvd4:16;
+} unm_niu_gb_mac_config_1_t;
+
+/*
+ * NIU XG Pause Ctl Register
+ */
+typedef struct {
+ unm_crbword_t
+ xg0_mask:1, /* 1:disable tx pause frames */
+ xg0_request:1, /* request single pause frame */
+ xg0_on_off:1, /* 1:req is pause on, 0:off */
+ xg1_mask:1, /* 1:disable tx pause frames */
+ xg1_request:1, /* request single pause frame */
+ xg1_on_off:1, /* 1:req is pause on, 0:off */
+ rsvd:26;
+} unm_niu_xg_pause_ctl_t;
+
+/*
+ * NIU GBe Pause Ctl Register
+ */
+typedef struct {
+ unm_crbword_t
+ gb0_mask:1, /* 1:disable tx pause frames */
+ gb0_pause_req:1, /* 1: send pause on, 0: send pause off */
+ gb1_mask:1, /* 1:disable tx pause frames */
+ gb1_pause_req:1, /* 1: send pause on, 0: send pause off */
+ gb2_mask:1, /* 1:disable tx pause frames */
+ gb2_pause_req:1, /* 1: send pause on, 0: send pause off */
+ gb3_mask:1, /* 1:disable tx pause frames */
+ gb3_pause_req:1, /* 1: send pause on, 0: send pause off */
+ rsvd:24;
+} unm_niu_gb_pause_ctl_t;
+
+
+/*
+ * NIU XG MAC Config Register
+ */
+typedef struct {
+ unm_crbword_t
+ tx_enable:1, /* 1:enable frame xmit, 0:disable */
+ rsvd1:1,
+ rx_enable:1, /* 1:enable frame recv, 0:disable */
+ rsvd2:1,
+ soft_reset:1, /* 1:reset the MAC , 0:no-op */
+ rsvd3:22,
+ xaui_framer_reset:1,
+ xaui_rx_reset:1,
+ xaui_tx_reset:1,
+ xg_ingress_afifo_reset:1,
+ xg_egress_afifo_reset:1;
+} unm_niu_xg_mac_config_0_t;
+
+/*
+ * NIU GB MII Mgmt Config Register (applies to GB0, GB1, GB2, GB3)
+ */
+typedef struct {
+ unm_crbword_t
+ clockselect:3, /* 0:clk/4, 1:clk/4, 2:clk/6, 3:clk/8 */
+ /* 4:clk/10, 5:clk/14, 6:clk/20, 7:clk/28 */
+ rsvd1:1,
+ nopreamble:1, /* 1:suppress preamble generation, 0:normal */
+ scanauto:1, /* ???? */
+ rsvd2:25,
+ reset:1; /* 1:reset MII mgmt, 0:no-op */
+} unm_niu_gb_mii_mgmt_config_t;
+
+/*
+ * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
+ */
+typedef struct {
+ unm_crbword_t
+ read_cycle:1, /* 1:perform single read cycle, 0:no-op */
+ scan_cycle:1, /* 1:perform continuous read cycles, 0:no-op */
+ rsvd:30;
+} unm_niu_gb_mii_mgmt_command_t;
+
+/*
+ * NIU GB MII Mgmt Address Register (applies to GB0, GB1, GB2, GB3)
+ */
+typedef struct {
+ unm_crbword_t
+ reg_addr:5, /* which mgmt register we want to talk to */
+ rsvd1:3,
+ phy_addr:5, /* which PHY to talk to (0 is reserved) */
+ rsvd:19;
+} unm_niu_gb_mii_mgmt_address_t;
+
+/*
+ * NIU GB MII Mgmt Indicators Register (applies to GB0, GB1, GB2, GB3)
+ * Read-only register.
+ */
+typedef struct {
+ unm_crbword_t
+ busy:1, /* 1:performing an MII mgmt cycle, 0:idle */
+ scanning:1, /* 1:scan operation in progress, 0:idle */
+ notvalid:1, /* 1:mgmt result data not yet valid, 0:idle */
+ rsvd:29;
+} unm_niu_gb_mii_mgmt_indicators_t;
+
+/*
+ * NIU GB Station Address High Register
+ * NOTE: this value is in network byte order.
+ */
+typedef struct {
+ unm_crbword_t
+ address:32; /* station address [47:16] */
+} unm_niu_gb_station_address_high_t;
+
+/*
+ * NIU GB Station Address Low Register
+ * NOTE: this value is in network byte order.
+ */
+typedef struct {
+ unm_crbword_t
+ rsvd:16,
+ address:16; /* station address [15:0] */
+} unm_niu_gb_station_address_low_t;
+
+/* ============================ PHY Definitions ========================== */
+/*
+ * PHY-Specific MII control/status registers.
+ */
+typedef enum {
+ UNM_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
+ UNM_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
+ UNM_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
+ UNM_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
+ UNM_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
+ UNM_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
+ UNM_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
+ UNM_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
+ UNM_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
+ UNM_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
+ UNM_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
+ UNM_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
+ UNM_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
+ UNM_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
+ UNM_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
+} unm_niu_phy_register_t;
+
+/*
+ * PHY-Specific Status Register (reg 17).
+ */
+typedef struct {
+ unm_crbword_t
+ jabber:1, /* 1:jabber detected, 0:not */
+ polarity:1, /* 1:polarity reversed, 0:normal */
+ recvpause:1, /* 1:receive pause enabled, 0:disabled */
+ xmitpause:1, /* 1:transmit pause enabled, 0:disabled */
+ energydetect:1, /* 1:sleep, 0:active */
+ downshift:1, /* 1:downshift, 0:no downshift */
+ crossover:1, /* 1:MDIX (crossover), 0:MDI (no crossover) */
+ cablelen:3, /* not valid in 10Mb/s mode */
+ /* 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m */
+ link:1, /* 1:link up, 0:link down */
+ resolved:1, /* 1:speed and duplex resolved, 0:not yet */
+ pagercvd:1, /* 1:page received, 0:page not received */
+ duplex:1, /* 1:full duplex, 0:half duplex */
+ speed:2, /* 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd */
+ rsvd:16;
+} unm_niu_phy_status_t;
+
+/*
+ * Interrupt Register definition
+ * This definition applies to registers 18 and 19 (int enable and int status).
+ */
+typedef struct {
+ unm_crbword_t
+ jabber:1,
+ polarity_changed:1,
+ reserved:2,
+ energy_detect:1,
+ downshift:1,
+ mdi_xover_changed:1,
+ fifo_over_underflow:1,
+ false_carrier:1,
+ symbol_error:1,
+ link_status_changed:1,
+ autoneg_completed:1,
+ page_received:1,
+ duplex_changed:1,
+ speed_changed:1,
+ autoneg_error:1,
+ rsvd:16;
+} unm_niu_phy_interrupt_t;
+
+/* ============================= 10GbE =============================== */
+/*
+ * NIU Mode Register.
+ */
+typedef struct {
+ unm_crbword_t
+ enable_fc:1, /* enable FibreChannel */
+ enable_ge:1, /* enable 10/100/1000 Ethernet */
+ enable_xgb:1, /* enable 10Gb Ethernet */
+ rsvd:29;
+} unm_niu_control_t;
+
+/* ========================== Interface Functions ======================= */
+
+/* Generic enable for GbE ports. Will detect the speed of the link. */
+long unm_niu_gbe_init_port(long port);
+
+/* XG Link status */
+#define XG_LINK_UP 0x10
+#define XG_LINK_DOWN 0x20
+
+#define XG_LINK_UP_P3 0x1
+#define XG_LINK_DOWN_P3 0x2
+#define XG_LINK_UNKNOWN_P3 0
+
+#define XG_LINK_STATE_P3_MASK 0xf
+#define XG_LINK_STATE_P3(pcifn, val) \
+ (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+
+#define MTU_MARGIN 100
+
+#define PF_LINK_SPEED_MHZ 100
+#define PF_LINK_SPEED_REG(pcifn) (CRB_PF_LINK_SPEED_1 + (((pcifn)/4)* 4))
+#define PF_LINK_SPEED_MASK 0xff
+#define PF_LINK_SPEED_VAL(pcifn, reg) \
+ (((reg) >> (8 * ((pcifn) & 0x3))) & PF_LINK_SPEED_MASK)
+
+
+
+/*
+ * Definitions relating to access/control of the CAM RAM
+ */
+
+typedef union {
+ struct {
+ /*
+ * =1 if watchdog is active.
+ * =0 if watchdog is inactive
+ * This is read-only for anyone
+ * but the watchdog itself.
+ */
+ unsigned int enabled: 1,
+ /*
+ * Set this to 1 to send disable
+ * request to watchdog . Watchdog
+ * will complete the shutdown
+ * process and acknowledge it
+ * by clearing this bit and the
+ * "enable" bit.
+ */
+ disable_request: 1,
+ /*
+ * Set this to 1 to send enable
+ * request to watchdog . Watchdog
+ * will complete the enable
+ * process and acknowledge it
+ * by clearing this bit and
+ * setting the "enable" bit.
+ */
+ enable_request: 1,
+ unused: 29;
+ } s1;
+ unm_crbword_t word;
+} dma_watchdog_ctrl_t;
+
+#define UNM_CAM_RAM_BASE (UNM_CRB_CAM + 0x02000)
+#define UNM_CAM_RAM(reg) (UNM_CAM_RAM_BASE + (reg))
+
+#define UNM_PORT_MODE_NONE 0
+#define UNM_PORT_MODE_XG 1
+#define UNM_PORT_MODE_GB 2
+#define UNM_PORT_MODE_802_3_AP 3
+#define UNM_PORT_MODE_AUTO_NEG 4
+#define UNM_PORT_MODE_AUTO_NEG_1G 5
+#define UNM_PORT_MODE_AUTO_NEG_XG 6
+#define UNM_PORT_MODE_ADDR (UNM_CAM_RAM(0x24))
+#define UNM_WOL_PORT_MODE (UNM_CAM_RAM(0x198))
+
+#define UNM_ROM_LOCK_ID (UNM_CAM_RAM(0x100))
+#define UNM_I2C_ROM_LOCK_ID (UNM_CAM_RAM(0x104))
+#define UNM_PHY_LOCK_ID (UNM_CAM_RAM(0x120))
+#define UNM_CRB_WIN_LOCK_ID (UNM_CAM_RAM(0x124))
+#define CAM_RAM_DMA_WATCHDOG_CTRL 0x14 /* See dma_watchdog_ctrl_t */
+#define UNM_EFUSE_CHIP_ID (UNM_CAM_RAM(0x18))
+
+#define UNM_FW_VERSION_MAJOR (UNM_CAM_RAM(0x150))
+#define UNM_FW_VERSION_MINOR (UNM_CAM_RAM(0x154))
+#define UNM_FW_VERSION_BUILD (UNM_CAM_RAM(0x168))
+#define UNM_FW_VERSION_SUB (UNM_CAM_RAM(0x158))
+#define UNM_TCP_FW_VERSION_MAJOR_ADDR (UNM_CAM_RAM(0x15c))
+#define UNM_TCP_FW_VERSION_MINOR_ADDR (UNM_CAM_RAM(0x160))
+#define UNM_TCP_FW_VERSION_SUB_ADDR (UNM_CAM_RAM(0x164))
+#define UNM_PCIE_REG(reg) (UNM_CRB_PCIE + (reg))
+
+#define PCIE_DCR (0x00d8)
+#define PCIE_DB_DATA2 (0x10070)
+#define PCIE_DB_CTRL (0x100a0)
+#define PCIE_DB_ADDR (0x100a4)
+#define PCIE_DB_DATA (0x100a8)
+#define PCIE_IMBUS_CONTROL (0x101b8)
+#define PCIE_SETUP_FUNCTION (0x12040)
+#define PCIE_SETUP_FUNCTION2 (0x12048)
+#define PCIE_TGT_SPLIT_CHICKEN (0x12080)
+#define PCIE_CHICKEN3 (0x120c8)
+#define PCIE_MAX_MASTER_SPLIT (0x14048)
+#define PCIE_MAX_DMA_XFER_SIZE (0x1404c)
+
+#define UNM_WOL_WAKE (UNM_CAM_RAM(0x180))
+#define UNM_WOL_CONFIG_NV (UNM_CAM_RAM(0x184))
+#define UNM_WOL_CONFIG (UNM_CAM_RAM(0x188))
+#define UNM_PRE_WOL_RX_ENABLE (UNM_CAM_RAM(0x18c))
+
+/*
+ * Following define address space withing PCIX CRB space to talk with
+ * devices on the storage side PCI bus.
+ */
+#define PCIX_PS_MEM_SPACE (0x90000)
+
+#define UNM_PCIX_PH_REG(reg) (UNM_CRB_PCIE + (reg))
+
+/*
+ * Configuration registers. These are the same offsets on both host and
+ * storage side PCI blocks.
+ */
+/* Used for PS PCI Memory access */
+#define PCIX_PS_OP_ADDR_LO (0x10000)
+#define PCIX_PS_OP_ADDR_HI (0x10004) /* via CRB (PS side only) */
+
+#define PCIX_MS_WINDOW (0x10204) /* UNUSED */
+
+#define PCIX_CRB_WINDOW (0x10210)
+#define PCIX_CRB_WINDOW_F0 (0x10210)
+#define PCIX_CRB_WINDOW_F1 (0x10230)
+#define PCIX_CRB_WINDOW_F2 (0x10250)
+#define PCIX_CRB_WINDOW_F3 (0x10270)
+#define PCIX_CRB_WINDOW_F4 (0x102ac)
+#define PCIX_CRB_WINDOW_F5 (0x102bc)
+#define PCIX_CRB_WINDOW_F6 (0x102cc)
+#define PCIX_CRB_WINDOW_F7 (0x102dc)
+#define PCIE_CRB_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_CRB_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_CRB_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_MN_WINDOW (0x10200)
+#define PCIX_MN_WINDOW_F0 (0x10200)
+#define PCIX_MN_WINDOW_F1 (0x10220)
+#define PCIX_MN_WINDOW_F2 (0x10240)
+#define PCIX_MN_WINDOW_F3 (0x10260)
+#define PCIX_MN_WINDOW_F4 (0x102a0)
+#define PCIX_MN_WINDOW_F5 (0x102b0)
+#define PCIX_MN_WINDOW_F6 (0x102c0)
+#define PCIX_MN_WINDOW_F7 (0x102d0)
+#define PCIE_MN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_MN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_MN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_SN_WINDOW (0x10208)
+#define PCIX_SN_WINDOW_F0 (0x10208)
+#define PCIX_SN_WINDOW_F1 (0x10228)
+#define PCIX_SN_WINDOW_F2 (0x10248)
+#define PCIX_SN_WINDOW_F3 (0x10268)
+#define PCIX_SN_WINDOW_F4 (0x102a8)
+#define PCIX_SN_WINDOW_F5 (0x102b8)
+#define PCIX_SN_WINDOW_F6 (0x102c8)
+#define PCIX_SN_WINDOW_F7 (0x102d8)
+#define PCIE_SN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define UNM_PCIX_PS_REG(reg) (UNM_CRB_PCIX_MD + (reg))
+#define UNM_PCIX_PS2_REG(reg) (UNM_CRB_PCIE2 + (reg))
+#define MANAGEMENT_COMMAND_REG (UNM_CRB_PCIE + (4))
+
+#define UNM_PH_INT_MASK (UNM_CRB_PCIE + PCIX_INT_MASK)
+
+/*
+ * CRB window register.
+ */
+typedef struct {
+ unm_crbword_t rsvd1:25,
+ addrbit:1, /* bit 25 of CRB address */
+ rsvd2:6;
+} unm_pcix_crb_window_t;
+
+/*
+ * Tell which interrupt source we want to operate on.
+ */
+typedef enum {
+ UNM_PCIX_INT_SRC_UNDEFINED = 0,
+ UNM_PCIX_INT_SRC_DMA0, /* DMA engine 0 */
+ UNM_PCIX_INT_SRC_DMA1, /* DMA engine 1 */
+ UNM_PCIX_INT_SRC_I2Q /* I2Q block */
+} unm_pcix_int_source_t;
+
+typedef enum {
+ UNM_PCIX_INT_SRC_UNDEFINEDSTATE = 0,
+ UNM_PCIX_INT_SRC_ALLOW, /* Allow this src to int. the host */
+ UNM_PCIX_INT_SRC_MASK /* Mask this src */
+} unm_pcix_int_state_t;
+
+/*
+ * PCIX Interrupt Mask Register.
+ */
+typedef struct {
+ /* 0=DMA0 not masked, 1=masked */
+ unm_crbword_t dma0:1,
+ /* 0=DMA1 not masked, 1=masked */
+ dma1:1,
+ /* 0=I2Q not masked, 1=masked */
+ i2q:1,
+ dma0_err:1,
+ dma1_err:1,
+ target_status:1,
+ mega_err:1,
+ ps_serr_int:1,
+ split_discard:1,
+ io_write_func0:1,
+ io_write_func1:1,
+ io_write_func2:1,
+ io_write_func3:1,
+ msi_write_func0:1,
+ msi_write_func1:1,
+ msi_write_func2:1,
+ msi_write_func3:1,
+ rsvd:15;
+} unm_pcix_int_mask_t;
+
+int unm_pcix_int_control(unm_pcix_int_source_t src,
+ unm_pcix_int_state_t state);
+
+#define UNM_SRE_INT_STATUS (UNM_CRB_SRE + 0x00034)
+#define UNM_SRE_BUF_CTL (UNM_CRB_SRE + 0x01000)
+#define UNM_SRE_PBI_ACTIVE_STATUS (UNM_CRB_SRE + 0x01014)
+#define UNM_SRE_SCRATCHPAD (UNM_CRB_SRE + 0x01018)
+#define UNM_SRE_L1RE_CTL (UNM_CRB_SRE + 0x03000)
+#define UNM_SRE_L2RE_CTL (UNM_CRB_SRE + 0x05000)
+
+// These are offset to a particular Peg's CRB base address
+#define CRB_REG_EX_PC 0x3c
+
+#define PEG_NETWORK_BASE(N) (UNM_CRB_PEG_NET_0 + (((N)&3) << 20))
+
+/*
+ * Definitions relating to enqueue/dequeue/control of the Queue Operations
+ * to either the Primary Queue Manager or the Secondary Queue Manager.
+ */
+
+/*
+ * General configuration constants.
+ */
+#define UNM_QM_MAX_SIDE 1
+
+/*
+ * Data movement registers (differs based on processor).
+ */
+#define UNM_QM_COMMAND (UNM_PCI_CAMQM + 0x00000)
+#define UNM_QM_STATUS (UNM_PCI_CAMQM + 0x00008)
+#define UNM_QM_DATA(W, P) (UNM_PCI_CAMQM + 0x00010 + \
+ (W)*sizeof (unm_dataword_t))
+#define UNM_QM_REPLY(W, P)(UNM_PCI_CAMQM + 0x00050 + \
+ (W)*sizeof (unm_dataword_t))
+
+/*
+ * Control commands to the QM block.
+ */
+#define UNM_QM_CMD_READ 0x0 /* interpret "readop" field */
+
+/*
+ * Platform-specific fields in the queue command word
+ */
+#define UNM_QM_CMD_SIDE 0
+/* Casper and Peg need this bit. PCI interface does not */
+#define UNM_QM_CMD_START 1
+
+
+/*
+ * Pegasus has two QM ports. This is the default one to use (unless
+ * QM async interface is called explicitly with other port).
+ */
+#define UNM_QM_DEFAULT_PORT 0
+
+/*
+ * Status result returned to caller of unm_qm_request_status()
+ */
+typedef enum {
+ /* error in HW - most likely PCI bug. retry */
+ unm_qm_status_unknown = 0,
+ unm_qm_status_done, /* done with last command */
+ unm_qm_status_busy, /* busy */
+ unm_qm_status_notfound, /* queue is empty to read or full to write */
+ unm_qm_status_error /* error (e.g. timeout) encountered */
+} unm_qm_result_t;
+
+/*
+ * Definitions relating to access/control of the I2Q h/w block.
+ */
+/*
+ * Configuration registers.
+ */
+#define UNM_I2Q_CONFIG (UNM_CRB_I2Q + 0x00000)
+#define UNM_I2Q_ENA_PCI_LO (UNM_CRB_I2Q + 0x00010)
+#define UNM_I2Q_ENA_PCI_HI (UNM_CRB_I2Q + 0x00014)
+#define UNM_I2Q_ENA_CASPER_LO (UNM_CRB_I2Q + 0x00018)
+#define UNM_I2Q_ENA_CASPER_HI (UNM_CRB_I2Q + 0x0001c)
+#define UNM_I2Q_ENA_QM_LO (UNM_CRB_I2Q + 0x00020)
+#define UNM_I2Q_ENA_QM_HI (UNM_CRB_I2Q + 0x00024)
+#define UNM_I2Q_CLR_PCI_LO (UNM_CRB_I2Q + 0x00030)
+#define UNM_I2Q_CLR_PCI_HI (UNM_CRB_I2Q + 0x00034)
+#define UNM_I2Q_CLR_CASPER_LO (UNM_CRB_I2Q + 0x00038)
+#define UNM_I2Q_CLR_CASPER_HI (UNM_CRB_I2Q + 0x0003c)
+#define UNM_I2Q_MSG_HDR_LO(I) (UNM_CRB_I2Q + 0x00100 + (I)*0x8)
+#define UNM_I2Q_MSG_HDR_HI(I) (UNM_CRB_I2Q + 0x00104 + (I)*0x8)
+
+/*
+ * List the bit positions in the registers of the interrupt sources.
+ */
+typedef enum {
+ UNM_I2Q_SRC_PCI32 = 0, /* PCI32 block */
+ UNM_I2Q_SRC_PCIE = 1, /* PCI-Express block */
+ UNM_I2Q_SRC_CASPER = 2, /* Casper */
+ UNM_I2Q_SRC_CASPER_ERR = 3, /* Casper error */
+ UNM_I2Q_SRC_PEG_0 = 4, /* Peg 0 */
+ UNM_I2Q_SRC_PEG_1 = 5, /* Peg 1 */
+ UNM_I2Q_SRC_PEG_2 = 6, /* Peg 2 */
+ UNM_I2Q_SRC_PEG_3 = 7, /* Peg 3 */
+ UNM_I2Q_SRC_PEG_DCACHE = 8, /* Peg Data cache */
+ UNM_I2Q_SRC_PEG_ICACHE = 9, /* Peg Instruction cache */
+ UNM_I2Q_SRC_DMA0 = 10, /* DMA engine 0 */
+ UNM_I2Q_SRC_DMA1 = 11, /* DMA engine 1 */
+ UNM_I2Q_SRC_DMA2 = 12, /* DMA engine 2 */
+ NM_I2Q_SRC_DMA3 = 13, /* DMA engine 3 */
+ UNM_I2Q_SRC_LPC = 14, /* */
+ UNM_I2Q_SRC_SMB = 15, /* */
+ UNM_I2Q_SRC_TIMER = 16, /* One of the global timers */
+ UNM_I2Q_SRC_SQG0 = 17, /* SQM SQG0 empty->non-empty */
+ UNM_I2Q_SRC_SQG1 = 18, /* SQM SQG1 empty->non-empty */
+ UNM_I2Q_SRC_SQG2 = 19, /* SQM SQG2 empty->non-empty */
+ UNM_I2Q_SRC_SQG3 = 20, /* SQM SQG3 empty->non-empty */
+ UNM_I2Q_SRC_SQG0_LW = 21, /* SQM SQG0 low on free buffers */
+ UNM_I2Q_SRC_SQG1_LW = 22, /* SQM SQG1 low on free buffers */
+ UNM_I2Q_SRC_SQG2_LW = 23, /* SQM SQG2 low on free buffers */
+ UNM_I2Q_SRC_SQG3_LW = 24, /* SQM SQG3 low on free buffers */
+ UNM_I2Q_SRC_PQM_0 = 25, /* PQM group 0 */
+ UNM_I2Q_SRC_PQM_1 = 26, /* PQM group 1 */
+ UNM_I2Q_SRC_PQM_2 = 27, /* PQM group 2 */
+ UNM_I2Q_SRC_PQM_3 = 28, /* PQM group 3 */
+ /* [29:31] reserved */
+ UNM_I2Q_SRC_SW_0 = 32, /* SW INT 0 */
+ UNM_I2Q_SRC_SW_1 = 33, /* SW INT 1 */
+ UNM_I2Q_SRC_SW_2 = 34, /* SW INT 2 */
+ UNM_I2Q_SRC_SW_3 = 35, /* SW INT 3 */
+ UNM_I2Q_SRC_SW_4 = 36, /* SW INT 4 */
+ UNM_I2Q_SRC_SW_5 = 37, /* SW INT 5 */
+ UNM_I2Q_SRC_SW_6 = 38, /* SW INT 6 */
+ UNM_I2Q_SRC_SW_7 = 39, /* SW INT 7 */
+ UNM_I2Q_SRC_SRE_EPG = 40, /* SRE/EPG aggregate interrupt */
+ UNM_I2Q_SRC_XDMA = 41, /* XDMA engine */
+ UNM_I2Q_SRC_MN = 42, /* DDR interface unit */
+ UNM_I2Q_SRC_NIU = 43, /* Network interface unit */
+ UNM_I2Q_SRC_SN = 44, /* QDR interface unit */
+ UNM_I2Q_SRC_CAM = 45, /* CAM */
+ UNM_I2Q_SRC_EXT1 = 46, /* External 1 */
+ UNM_I2Q_SRC_EXT2 = 47, /* External 2 */
+ /* [48:63] reserved */
+ UNM_I2Q_SRC_MAX = 47, /* max used interrupt line */
+ UNM_I2Q_SRC_MAX_LO = 32, /* max bits in "lo" register */
+} unm_i2q_source_t;
+
+/*
+ * Interrupt Source Enable/Clear registers for the I2Q.
+ */
+typedef struct {
+ unm_crbword_t source:32; /* int enable/status bits */
+} unm_i2q_source_lo_t;
+
+typedef struct {
+ unm_crbword_t source:16, /* int enable/status bits */
+ rsvd:16;
+} unm_i2q_source_hi_t;
+
+/*
+ * List the possible interrupt sources and the
+ * control operations to be performed for each.
+ */
+typedef enum {
+ UNM_I2Q_CTL_SRCUNKNOWN = 0, /* undefined */
+ UNM_I2Q_CTL_PCI, /* PCI block */
+ UNM_I2Q_CTL_CASPER, /* Casper */
+ UNM_I2Q_CTL_QM /* Queue Manager */
+} unm_i2q_ctl_src_t;
+
+typedef enum {
+ UNM_I2Q_CTL_OPUNKNOWN = 0, /* undefined */
+ UNM_I2Q_CTL_ADD, /* add int'ing for that source */
+ UNM_I2Q_CTL_DEL /* stop int'ing for that source */
+} unm_i2q_ctl_op_t;
+
+/*
+ * Definitions relating to access/control of the Secondary Queue Manager
+ * h/w block.
+ */
+/*
+ * Configuration registers.
+ */
+#define UNM_SQM_BASE(G) \
+ ((G) == 0 ? UNM_CRB_SQM_NET_0 : \
+ ((G) == 1 ? UNM_CRB_SQM_NET_1 : \
+ ((G) == 2 ? UNM_CRB_SQM_NET_2 : UNM_CRB_SQM_NET_3)))
+
+#define UNM_SQM_INT_ENABLE(G) (UNM_SQM_BASE(G) + 0x00018)
+#define UNM_SQM_INT_STATUS(G) (UNM_SQM_BASE(G) + 0x0001c)
+#define UNN_SQM_SCRATCHPAD(G) (UNM_SQM_BASE(G) + 0x01000)
+
+#define UNM_SQM_MAX_GRP 4 /* num groups per side */
+#define UNM_SQM_MAX_SUBQ 16 /* num Q's per type-0 group */
+#define UNM_SQM_MAX_SUBGRP 4 /* subgrps per type-1 group */
+
+#define UNM_SQM_MAX_TYPE_1_NUM (256*1024)
+
+/*
+ * Interrupt enables and interrupt status for all 16 queues in a group.
+ */
+typedef struct {
+ unm_crbword_t queues:16, /* enable/status: 0x1=Q0, 0x8000=Q15 */
+ rsvd:16;
+} unm_sqm_int_enstat_t;
+
+/*
+ * Control operation for an SQM Group interrupt.
+ */
+typedef enum {
+ UNM_SQM_INTOP_OPUNKNOWN = 0, /* undefined */
+ UNM_SQM_INTOP_GET, /* return all bits for that group */
+ UNM_SQM_INTOP_SET, /* assign all bits for that group */
+ UNM_SQM_INTOP_ADD, /* set one bit for that group */
+ UNM_SQM_INTOP_DEL /* clear one bit for that group */
+} unm_sqm_int_op_t;
+typedef enum {
+ UNM_SQM_INTARG_ARGUNKNOWN = 0, /* undefined */
+ UNM_SQM_INTARG_ENABLE, /* affect the 'enable' register */
+ UNM_SQM_INTARG_STATUS /* affect the 'status' register */
+} unm_sqm_int_arg_t;
+
+int unm_sqm_int_control(unm_sqm_int_op_t op, unm_sqm_int_arg_t arg,
+ int side, int group, int queue, int *image);
+
+
+int unm_crb_read(unsigned long off, void *data);
+native_t unm_crb_read_val(unsigned long off);
+int unm_crb_write(unsigned long off, void *data);
+int unm_crb_writelit(unsigned long off, int data);
+int unm_imb_read(unsigned long off, void *data);
+int unm_imb_write(unsigned long off, void *data);
+int unm_imb_writelit64(unsigned long off, __uint64_t data);
+
+unsigned long unm_xport_lock(void);
+void unm_xport_unlock(unsigned long);
+
+#define UNM_CRB_READ_VAL(ADDR) unm_crb_read_val((ADDR))
+#define UNM_CRB_READ(ADDR, VALUE) unm_crb_read((ADDR), (unm_crbword_t *)(VALUE))
+#define UNM_CRB_READ_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_crb_read(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+#define UNM_CRB_WRITE_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_crb_write(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+#define UNM_CRB_WRITELIT(ADDR, VALUE) \
+ do { \
+ unm_crb_writelit(ADDR, VALUE); \
+ } while (0)
+#define UNM_CRB_WRITE(ADDR, VALUE) \
+ do { \
+ unm_crb_write(ADDR, VALUE); \
+ } while (0)
+#define UNM_CRB_WRITELIT_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_crb_writelit(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+
+#define UNM_IMB_READ_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_imb_read(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+#define UNM_IMB_WRITE_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_imb_write(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+#define UNM_IMB_WRITELIT_CHECK(ADDR, VALUE) \
+ do { \
+ if (unm_imb_writelit64(ADDR, VALUE)) \
+ return (-1); \
+ } while (0)
+
+/*
+ * Configuration registers.
+ */
+#ifdef PCIX
+#define UNM_DMA_BASE(U) (UNM_CRB_PCIX_HOST + 0x20000 + ((U)<<16))
+#else
+#define UNM_DMA_BASE(U) (UNM_CRB_PCIX_MD + 0x20000 + ((U)<<16))
+#endif
+#define UNM_DMA_COMMAND(U) (UNM_DMA_BASE(U) + 0x00008)
+
+
+#define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */
+#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */
+#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */
+#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */
+#define PCIE_SEM4_LOCK (0x1c020) /* I2C lock */
+#define PCIE_SEM4_UNLOCK (0x1c024) /* I2C unlock */
+#define PCIE_SEM5_LOCK (0x1c028) /* API lock */
+#define PCIE_SEM5_UNLOCK (0x1c02c) /* API unlock */
+#define PCIE_SEM6_LOCK (0x1c030) /* sw lock */
+#define PCIE_SEM6_UNLOCK (0x1c034) /* sw unlock */
+#define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */
+#define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock */
+
+
+#define PCIE_PS_STRAP_RESET (0x18000)
+
+#define M25P_INSTR_WREN 0x06
+#define M25P_INSTR_RDSR 0x05
+#define M25P_INSTR_PP 0x02
+#define M25P_INSTR_SE 0xd8
+#define CAM_RAM_P2I_ENABLE 0xc
+#define CAM_RAM_P2D_ENABLE 0x8
+#define PCIX_IMBTAG (0x18004)
+#define UNM_MAC_ADDR_CNTL_REG (UNM_CRB_NIU + 0x1000)
+
+#define UNM_MULTICAST_ADDR_HI_0 (UNM_CRB_NIU + 0x1010)
+#define UNM_MULTICAST_ADDR_HI_1 (UNM_CRB_NIU + 0x1014)
+#define UNM_MULTICAST_ADDR_HI_2 (UNM_CRB_NIU + 0x1018)
+#define UNM_MULTICAST_ADDR_HI_3 (UNM_CRB_NIU + 0x101c)
+
+#define M_UNICAST_ADDR_BASE (UNM_CRB_NIU + 0x1080)
+
+#define UNM_UNICAST_ADDR_LO_0_0 (UNM_CRB_NIU + 0x1080) // port 0
+#define UNM_UNICAST_ADDR_HI_0_0 (UNM_CRB_NIU + 0x1084)
+#define UNM_UNICAST_ADDR_LO_0_1 (UNM_CRB_NIU + 0x1088)
+#define UNM_UNICAST_ADDR_HI_0_1 (UNM_CRB_NIU + 0x108c)
+#define UNM_UNICAST_ADDR_LO_0_2 (UNM_CRB_NIU + 0x1090)
+#define UNM_UNICAST_ADDR_HI_0_2 (UNM_CRB_NIU + 0x1084)
+#define UNM_UNICAST_ADDR_LO_0_3 (UNM_CRB_NIU + 0x1098)
+#define UNM_UNICAST_ADDR_HI_0_3 (UNM_CRB_NIU + 0x109c)
+
+#define UNM_UNICAST_ADDR_LO_1_0 (UNM_CRB_NIU + 0x10a0)
+#define UNM_UNICAST_ADDR_HI_1_0 (UNM_CRB_NIU + 0x10a4)
+#define UNM_UNICAST_ADDR_LO_1_1 (UNM_CRB_NIU + 0x10a8)
+#define UNM_UNICAST_ADDR_HI_1_1 (UNM_CRB_NIU + 0x10ac)
+#define UNM_UNICAST_ADDR_LO_1_2 (UNM_CRB_NIU + 0x10b0)
+#define UNM_UNICAST_ADDR_HI_1_2 (UNM_CRB_NIU + 0x10b4)
+#define UNM_UNICAST_ADDR_LO_1_3 (UNM_CRB_NIU + 0x10b8)
+#define UNM_UNICAST_ADDR_HI_1_3 (UNM_CRB_NIU + 0x10bc)
+
+#define UNM_UNICAST_ADDR_LO_2_0 (UNM_CRB_NIU + 0x10c0)
+#define UNM_UNICAST_ADDR_HI_2_0 (UNM_CRB_NIU + 0x10c4)
+#define UNM_UNICAST_ADDR_LO_2_1 (UNM_CRB_NIU + 0x10c8)
+#define UNM_UNICAST_ADDR_HI_2_1 (UNM_CRB_NIU + 0x10cc)
+#define UNM_UNICAST_ADDR_LO_2_2 (UNM_CRB_NIU + 0x10d0)
+#define UNM_UNICAST_ADDR_HI_2_2 (UNM_CRB_NIU + 0x10d4)
+#define UNM_UNICAST_ADDR_LO_2_3 (UNM_CRB_NIU + 0x10d8)
+#define UNM_UNICAST_ADDR_HI_2_3 (UNM_CRB_NIU + 0x10dc)
+
+#define UNM_UNICAST_ADDR_LO_3_0 (UNM_CRB_NIU + 0x10e0)
+#define UNM_UNICAST_ADDR_HI_3_0 (UNM_CRB_NIU + 0x10e4)
+#define UNM_UNICAST_ADDR_LO_3_1 (UNM_CRB_NIU + 0x10e8)
+#define UNM_UNICAST_ADDR_HI_3_1 (UNM_CRB_NIU + 0x10ec)
+#define UNM_UNICAST_ADDR_LO_3_2 (UNM_CRB_NIU + 0x10f0)
+#define UNM_UNICAST_ADDR_HI_3_2 (UNM_CRB_NIU + 0x10f4)
+#define UNM_UNICAST_ADDR_LO_3_3 (UNM_CRB_NIU + 0x10f8)
+#define UNM_UNICAST_ADDR_HI_3_3 (UNM_CRB_NIU + 0x10fc)
+
+#define UNM_MULTICAST_ADDR_BASE (UNM_CRB_NIU + 0x1100)
+
+// BASE ADDRESS FOR POOL/PORT 0
+#define UNM_MULTICAST_ADDR_LO_0 (UNM_CRB_NIU + 0x1100)
+// FOR PORT 1
+#define UNM_MULTICAST_ADDR_LO_1 (UNM_CRB_NIU + 0x1180)
+// FOR PORT 2
+#define UNM_MULTICAST_ADDR_LO_2 (UNM_CRB_NIU + 0x1200)
+// PORT 3
+#define UNM_MULTICAST_ADDR_LO_3 (UNM_CRB_NIU + 0x1280)
+
+#define PHAN_VENDOR_ID 0x4040
+
+#define CAM_RAM_PEG_ENABLES 0x4
+
+/*
+ * The PCI VendorID and DeviceID for our board.
+ */
+#define PCI_VENDOR_ID_NX 0x4040
+#define PCI_DEVICE_ID_NX_XG 0x0001
+#define PCI_DEVICE_ID_NX_CX4 0x0002
+#define PCI_DEVICE_ID_NX_QG 0x0003
+#define PCI_DEVICE_ID_NX_IMEZ 0x0004
+#define PCI_DEVICE_ID_NX_HMEZ 0x0005
+#define PCI_DEVICE_ID_NX_IMEZ_DUP 0x0024
+#define PCI_DEVICE_ID_NX_HMEZ_DUP 0x0025
+#define PCI_DEVICE_ID_NX_P3_XG 0x0100
+
+/*
+ * Time base tick control registers (global and per-flow).
+ */
+
+typedef struct {
+ /* half period of time cycle */
+ /* global: in units of core clock */
+ /* per-flow: in units of global ticks */
+ unm_crbword_t count:16,
+ rsvd:15,
+ enable:1; /* 0=disable, 1=enable */
+} unm_timer_tickctl_t;
+
+
+typedef struct
+{
+ unm_crbword_t
+ id_pool_0:2,
+ enable_xtnd_0:1,
+ rsvd1:1,
+ id_pool_1:2,
+ enable_xtnd_1:1,
+ rsvd2:1,
+ id_pool_2:2,
+ enable_xtnd_2:1,
+ rsvd3:1,
+ id_pool_3:2,
+ enable_xtnd_3:1,
+ rsvd4:9,
+ mode_select:2,
+ rsvd5:2,
+ enable_pool:4;
+} unm_mac_addr_cntl_t;
+
+typedef struct {
+ unm_crbword_t start:1,
+ enable:1,
+ command:1,
+ busy:1,
+ rsvd:28;
+} unm_miu_test_agt_ctrl_t;
+
+#define UNM_MIU_TEST_AGENT_CMD_READ 0
+#define UNM_MIU_TEST_AGENT_CMD_WRITE 1
+#define UNM_MIU_TEST_AGENT_BUSY 1
+#define UNM_MIU_TEST_AGENT_ENABLE 1
+#define UNM_MIU_TEST_AGENT_START 1
+
+#define UNM_MIU_MN_CONTROL (UNM_CRB_DDR_NET + MIU_CONTROL)
+#define UNM_MIU_MN_TAG (UNM_CRB_DDR_NET + MIU_TAG)
+#define UNM_MIU_MN_TEST_AGT_ADDR_LO (UNM_CRB_DDR_NET + MIU_TEST_AGT_ADDR_LO)
+#define UNM_MIU_MN_TEST_AGT_ADDR_HI (UNM_CRB_DDR_NET + MIU_TEST_AGT_ADDR_HI)
+#define UNM_MIU_MN_TEST_AGT_WRDATA_LO (UNM_CRB_DDR_NET + MIU_TEST_AGT_WRDATA_LO)
+#define UNM_MIU_MN_TEST_AGT_WRDATA_HI (UNM_CRB_DDR_NET + MIU_TEST_AGT_WRDATA_HI)
+#define UNM_MIU_MN_TEST_AGT_CTRL (UNM_CRB_DDR_NET + MIU_TEST_AGT_CTRL)
+#define UNM_MIU_MN_TEST_AGT_RDDATA_LO (UNM_CRB_DDR_NET + MIU_TEST_AGT_RDDATA_LO)
+#define UNM_MIU_MN_TEST_AGT_RDDATA_HI (UNM_CRB_DDR_NET + MIU_TEST_AGT_RDDATA_HI)
+
+#define UNM_SIU_SN_TEST_AGT_ADDR_LO (UNM_CRB_QDR_NET + SIU_TEST_AGT_ADDR_LO)
+#define UNM_SIU_SN_TEST_AGT_ADDR_HI (UNM_CRB_QDR_NET + SIU_TEST_AGT_ADDR_HI)
+#define UNM_SIU_SN_TEST_AGT_WRDATA_LO (UNM_CRB_QDR_NET + SIU_TEST_AGT_WRDATA_LO)
+#define UNM_SIU_SN_TEST_AGT_WRDATA_HI (UNM_CRB_QDR_NET + SIU_TEST_AGT_WRDATA_HI)
+#define UNM_SIU_SN_TEST_AGT_CTRL (UNM_CRB_QDR_NET + SIU_TEST_AGT_CTRL)
+#define UNM_SIU_SN_TEST_AGT_RDDATA_LO (UNM_CRB_QDR_NET + SIU_TEST_AGT_RDDATA_LO)
+#define UNM_SIU_SN_TEST_AGT_RDDATA_HI (UNM_CRB_QDR_NET + SIU_TEST_AGT_RDDATA_HI)
+
+#define NX_IS_SYSTEM_CUT_THROUGH(MIU_CTRL) (((MIU_CTRL) & 0x4) ? 1 : 0)
+#define NX_SET_SYSTEM_LEGACY(MIU_CTRL) {(MIU_CTRL) &= ~0x4; }
+#define NX_SET_SYSTEM_CUT_THROUGH(MIU_CTRL) {(MIU_CTRL) |= 0x4; }
+
+#endif /* __UNM_INC_H */
diff --git a/usr/src/uts/common/io/ntxn/unm_ndd.c b/usr/src/uts/common/io/ntxn/unm_ndd.c
new file mode 100644
index 0000000000..c338396955
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_ndd.c
@@ -0,0 +1,499 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include "unm_nic.h"
+
+static char transfer_speed_propname[] = "transfer-speed";
+static char speed_propname[] = "speed";
+static char duplex_propname[] = "full-duplex";
+
+/*
+ * Notes:
+ * The first character of the <name> field encodes the read/write
+ * status of the parameter:
+ * '-' => read-only,
+ * '+' => read/write,
+ * '!' => invisible!
+ *
+ * For writable parameters, we check for a driver property with the
+ * same name; if found, and its value is in range, we initialise
+ * the parameter from the property, overriding the default in the
+ * table below.
+ *
+ * A NULL in the <name> field terminates the array.
+ *
+ * The <info> field is used here to provide the index of the
+ * parameter to be initialised; thus it doesn't matter whether
+ * this table is kept ordered or not.
+ *
+ * The <info> field in the per-instance copy, on the other hand,
+ * is used to count assignments so that we can tell when a magic
+ * parameter has been set via ndd (see unm_param_set()).
+ */
+static const nd_param_t nd_template_10000[] = {
+/* info min max init r/w+name */
+
+/* Our hardware capabilities */
+{ PARAM_AUTONEG_CAP, 0, 1, 1, "-autoneg_cap" },
+{ PARAM_PAUSE_CAP, 0, 1, 1, "-pause_cap" },
+{ PARAM_ASYM_PAUSE_CAP, 0, 1, 1, "-asym_pause_cap" },
+{ PARAM_10000FDX_CAP, 0, 1, 1, "-10000fdx_cap" },
+{ PARAM_1000FDX_CAP, 0, 1, 0, "-1000fdx_cap" },
+{ PARAM_1000HDX_CAP, 0, 1, 0, "-1000hdx_cap" },
+{ PARAM_100T4_CAP, 0, 1, 0, "-100T4_cap" },
+{ PARAM_100FDX_CAP, 0, 1, 0, "-100fdx_cap" },
+{ PARAM_100HDX_CAP, 0, 1, 0, "-100hdx_cap" },
+{ PARAM_10FDX_CAP, 0, 1, 0, "-10fdx_cap" },
+{ PARAM_10HDX_CAP, 0, 1, 0, "-10hdx_cap" },
+
+/* Our advertised capabilities */
+{ PARAM_ADV_AUTONEG_CAP, 0, 1, 1, "-adv_autoneg_cap" },
+{ PARAM_ADV_PAUSE_CAP, 0, 1, 1, "+adv_pause_cap" },
+{ PARAM_ADV_ASYM_PAUSE_CAP, 0, 1, 1, "+adv_asym_pause_cap" },
+{ PARAM_ADV_10000FDX_CAP, 0, 1, 1, "+adv_10000fdx_cap" },
+{ PARAM_ADV_1000FDX_CAP, 0, 1, 0, "+adv_1000fdx_cap" },
+{ PARAM_ADV_1000HDX_CAP, 0, 1, 0, "-adv_1000hdx_cap" },
+{ PARAM_ADV_100T4_CAP, 0, 1, 0, "-adv_100T4_cap" },
+{ PARAM_ADV_100FDX_CAP, 0, 1, 0, "+adv_100fdx_cap" },
+{ PARAM_ADV_100HDX_CAP, 0, 1, 0, "+adv_100hdx_cap" },
+{ PARAM_ADV_10FDX_CAP, 0, 1, 0, "+adv_10fdx_cap" },
+{ PARAM_ADV_10HDX_CAP, 0, 1, 0, "+adv_10hdx_cap" },
+
+/* Current operating modes */
+{ PARAM_LINK_STATUS, 0, 1, 0, "-link_status" },
+{ PARAM_LINK_SPEED, 0, 10000, 0, "-link_speed" },
+{ PARAM_LINK_DUPLEX, 0, 2, 0, "-link_duplex" },
+
+/* Loopback status */
+{ PARAM_LOOP_MODE, 0, 2, 0, "-loop_mode" },
+
+/* Terminator */
+{ PARAM_COUNT, 0, 0, 0, NULL }
+};
+
+static const nd_param_t nd_template_1000[] = {
+/* info min max init r/w+name */
+
+/* Our hardware capabilities */
+{ PARAM_AUTONEG_CAP, 0, 1, 1, "-autoneg_cap" },
+{ PARAM_PAUSE_CAP, 0, 1, 1, "-pause_cap" },
+{ PARAM_ASYM_PAUSE_CAP, 0, 1, 1, "-asym_pause_cap" },
+{ PARAM_1000FDX_CAP, 0, 1, 1, "-1000fdx_cap" },
+{ PARAM_1000HDX_CAP, 0, 1, 0, "-1000hdx_cap" },
+{ PARAM_100T4_CAP, 0, 1, 0, "-100T4_cap" },
+{ PARAM_100FDX_CAP, 0, 1, 1, "-100fdx_cap" },
+{ PARAM_100HDX_CAP, 0, 1, 1, "-100hdx_cap" },
+{ PARAM_10FDX_CAP, 0, 1, 1, "-10fdx_cap" },
+{ PARAM_10HDX_CAP, 0, 1, 1, "-10hdx_cap" },
+
+/* Our advertised capabilities */
+{ PARAM_ADV_AUTONEG_CAP, 0, 1, 1, "-adv_autoneg_cap" },
+{ PARAM_ADV_PAUSE_CAP, 0, 1, 1, "+adv_pause_cap" },
+{ PARAM_ADV_ASYM_PAUSE_CAP, 0, 1, 1, "+adv_asym_pause_cap" },
+{ PARAM_ADV_1000FDX_CAP, 0, 1, 1, "+adv_1000fdx_cap" },
+{ PARAM_ADV_1000HDX_CAP, 0, 1, 0, "-adv_1000hdx_cap" },
+{ PARAM_ADV_100T4_CAP, 0, 1, 0, "-adv_100T4_cap" },
+{ PARAM_ADV_100FDX_CAP, 0, 1, 1, "+adv_100fdx_cap" },
+{ PARAM_ADV_100HDX_CAP, 0, 1, 1, "+adv_100hdx_cap" },
+{ PARAM_ADV_10FDX_CAP, 0, 1, 1, "+adv_10fdx_cap" },
+{ PARAM_ADV_10HDX_CAP, 0, 1, 1, "+adv_10hdx_cap" },
+
+/* Current operating modes */
+{ PARAM_LINK_STATUS, 0, 1, 0, "-link_status" },
+{ PARAM_LINK_SPEED, 0, 1000, 0, "-link_speed" },
+{ PARAM_LINK_DUPLEX, 0, 2, 0, "-link_duplex" },
+
+/* Loopback status */
+{ PARAM_LOOP_MODE, 0, 2, 0, "-loop_mode" },
+
+/* Terminator */
+{ PARAM_COUNT, 0, 0, 0, NULL }
+};
+
+/* ============== NDD Support Functions =============== */
+
+/*
+ * Extracts the value from the unm parameter array and prints
+ * the parameter value. cp points to the required parameter.
+ */
+/* ARGSUSED */
+static int
+unm_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
+{
+ nd_param_t *ndp;
+
+ ndp = (nd_param_t *)(uintptr_t)cp;
+ (void) mi_mpprintf(mp, "%d", ndp->ndp_val);
+
+ return (0);
+}
+
+/*
+ * Validates the request to set a UNM parameter to a specific value.
+ * If the request is OK, the parameter is set. Also the <info> field
+ * is incremented to show that the parameter was touched, even though
+ * it may have been set to the same value it already had.
+ */
+/* ARGSUSED */
+static int
+unm_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
+{
+ nd_param_t *ndp;
+ int new_value;
+ char *end;
+
+ ndp = (nd_param_t *)(uintptr_t)cp;
+ new_value = mi_strtol(value, &end, 10);
+ if (end == value)
+ return (EINVAL);
+ if (new_value < ndp->ndp_min || new_value > ndp->ndp_max)
+ return (EINVAL);
+
+ ndp->ndp_val = new_value;
+ ndp->ndp_info += 1;
+ return (0);
+}
+
+/*
+ * Initialise the per-instance parameter array from the global prototype,
+ * and register each element with the named dispatch handler using nd_load()
+ */
+static int
+unm_param_register(unm_adapter *adapter)
+{
+ const nd_param_t *tmplp;
+ dev_info_t *dip;
+ nd_param_t *ndp;
+ caddr_t *nddpp;
+ pfi_t setfn;
+ char *nm;
+ int pval;
+
+ dip = adapter->dip;
+ nddpp = &adapter->nd_data_p;
+ ASSERT(*nddpp == NULL);
+
+ if (adapter->ahw.board_type == UNM_NIC_XGBE)
+ tmplp = nd_template_10000;
+ else
+ tmplp = nd_template_1000;
+
+ for (; tmplp->ndp_name != NULL; ++tmplp) {
+ /*
+ * Copy the template from nd_template[] into the
+ * proper slot in the per-instance parameters,
+ * then register the parameter with nd_load()
+ */
+ ndp = &adapter->nd_params[tmplp->ndp_info];
+ *ndp = *tmplp;
+ nm = &ndp->ndp_name[0];
+ setfn = unm_param_set;
+
+ switch (*nm) {
+ default:
+ case '!':
+ continue;
+
+ case '+':
+ break;
+
+ case '-':
+ setfn = NULL;
+ break;
+ }
+
+ if (!nd_load(nddpp, ++nm, unm_param_get, setfn, (caddr_t)ndp))
+ goto nd_fail;
+
+ /*
+ * If the parameter is writable, and there's a property
+ * with the same name, and its value is in range, we use
+ * it to initialise the parameter. If it exists but is
+ * out of range, it's ignored.
+ */
+ if (setfn && UNM_PROP_EXISTS(dip, nm)) {
+ pval = UNM_PROP_GET_INT(dip, nm);
+ if (pval >= ndp->ndp_min && pval <= ndp->ndp_max)
+ ndp->ndp_val = pval;
+ }
+ }
+
+ DPRINTF(1, (CE_WARN, "unm_param_register: OK"));
+ return (DDI_SUCCESS);
+
+nd_fail:
+ if (adapter->ahw.board_type == UNM_NIC_XGBE) {
+ cmn_err(CE_WARN,
+ "unm_param_register: FAILED at index %d [info %d]",
+ (int)(tmplp-nd_template_10000), tmplp->ndp_info);
+ } else {
+ cmn_err(CE_WARN,
+ "unm_param_register: FAILED at index %d [info %d]",
+ (int)(tmplp-nd_template_1000), tmplp->ndp_info);
+ }
+ nd_free(nddpp);
+ return (DDI_FAILURE);
+}
+
+int
+unm_nd_init(unm_adapter *adapter)
+{
+ dev_info_t *dip;
+ int duplex;
+ int speed;
+
+ /*
+ * Register all the per-instance properties, initialising
+ * them from the table above or from driver properties set
+ * in the .conf file
+ */
+ if (unm_param_register(adapter) != DDI_SUCCESS)
+ return (-1);
+
+ /*
+ * The link speed may be forced to 1000 or 10000 Mbps using
+ * the property "transfer-speed". This may be done in OBP by
+ * using the command "apply transfer-speed=<speed> <device>".
+ * The speed may be 1000 or 10000 - any other value will be
+ * ignored. Note that this does *enables* autonegotiation, but
+ * restricts it to the speed specified by the property.
+ */
+ dip = adapter->dip;
+ if (UNM_PROP_EXISTS(dip, transfer_speed_propname)) {
+
+ speed = UNM_PROP_GET_INT(dip, transfer_speed_propname);
+
+ switch (speed) {
+ case 10000:
+ adapter->param_adv_autoneg = 1;
+ adapter->param_adv_10000fdx = 1;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 1000:
+ adapter->param_adv_autoneg = 1;
+ adapter->param_adv_1000fdx = 1;
+ adapter->param_adv_1000hdx = 1;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 100:
+ adapter->param_adv_autoneg = 1;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100fdx = 1;
+ adapter->param_adv_100hdx = 1;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 10:
+ adapter->param_adv_autoneg = 1;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10fdx = 1;
+ adapter->param_adv_10hdx = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Also check the "speed" and "full-duplex" properties. Setting
+ * these properties will override all other settings and *disable*
+ * autonegotiation, so both should be specified if either one is.
+ * Otherwise, the unspecified parameter will be set to a default
+ * value (10000Mb/s, full-duplex).
+ */
+ if (UNM_PROP_EXISTS(dip, speed_propname) ||
+ UNM_PROP_EXISTS(dip, duplex_propname)) {
+
+ adapter->param_adv_autoneg = 0;
+ adapter->param_adv_10000fdx = 1;
+ adapter->param_adv_1000fdx = 1;
+ adapter->param_adv_1000hdx = 1;
+ adapter->param_adv_100fdx = 1;
+ adapter->param_adv_100hdx = 1;
+ adapter->param_adv_10fdx = 1;
+ adapter->param_adv_10hdx = 1;
+
+ speed = UNM_PROP_GET_INT(dip, speed_propname);
+ duplex = UNM_PROP_GET_INT(dip, duplex_propname);
+
+ switch (speed) {
+ case 10000:
+ default:
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 1000:
+ adapter->param_adv_10000fdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 100:
+ adapter->param_adv_10000fdx = 0;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_10fdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 10:
+ adapter->param_adv_10000fdx = 0;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_100hdx = 0;
+ break;
+ }
+
+ switch (duplex) {
+ default:
+ case 1:
+ adapter->param_adv_1000hdx = 0;
+ adapter->param_adv_100hdx = 0;
+ adapter->param_adv_10hdx = 0;
+ break;
+
+ case 0:
+ adapter->param_adv_10000fdx = 0;
+ adapter->param_adv_1000fdx = 0;
+ adapter->param_adv_100fdx = 0;
+ adapter->param_adv_10fdx = 0;
+ break;
+ }
+ }
+
+ DPRINTF(1, (CE_WARN, "unm_nd_init: autoneg %d"
+ "pause %d asym_pause %d "
+ "10000fdx %d "
+ "1000fdx %d 1000hdx %d "
+ "100fdx %d 100hdx %d "
+ "10fdx %d 10hdx %d ",
+ adapter->param_adv_autoneg,
+ adapter->param_adv_pause, adapter->param_adv_asym_pause,
+ adapter->param_adv_10000fdx,
+ adapter->param_adv_1000fdx, adapter->param_adv_1000hdx,
+ adapter->param_adv_100fdx, adapter->param_adv_100hdx,
+ adapter->param_adv_10fdx, adapter->param_adv_10hdx));
+
+ return (0);
+}
+
+enum ioc_reply
+unm_nd_ioctl(unm_adapter *adapter, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
+{
+ boolean_t ok;
+ int cmd;
+
+ DPRINTF(1, (CE_WARN, "unm_nd_ioctl($%p, $%p, $%p, $%p)",
+ (void *)adapter, (void *)wq, (void *)mp, (void *)iocp));
+
+ cmd = iocp->ioc_cmd;
+ switch (cmd) {
+ default:
+ /* NOTREACHED */
+ DPRINTF(-1, (CE_WARN, "unm_nd_ioctl: invalid cmd 0x%x", cmd));
+ return (IOC_INVAL);
+
+ case ND_GET:
+ /*
+ * If nd_getset() returns B_FALSE, the command was
+ * not valid (e.g. unknown name), so we just tell the
+ * top-level ioctl code to send a NAK (with code EINVAL).
+ *
+ * Otherwise, nd_getset() will have built the reply to
+ * be sent (but not actually sent it), so we tell the
+ * caller to send the prepared reply.
+ */
+ ok = nd_getset(wq, adapter->nd_data_p, mp);
+ DPRINTF(1, (CE_WARN, "unm_nd_ioctl: get %s", ok ? "OK" :
+ "FAIL"));
+ return (ok ? IOC_REPLY : IOC_INVAL);
+
+ case ND_SET:
+ /*
+ * All adv_* parameters are locked (read-only) while
+ * the device is in any sort of loopback mode ...
+ */
+ if (adapter->param_loop_mode != UNM_LOOP_NONE) {
+ iocp->ioc_error = EBUSY;
+ return (IOC_INVAL);
+ }
+
+ ok = nd_getset(wq, adapter->nd_data_p, mp);
+
+ /*
+ * If nd_getset() returns B_FALSE, the command was
+ * not valid (e.g. unknown name), so we just tell
+ * the top-level ioctl code to send a NAK (with code
+ * EINVAL by default).
+ *
+ * Otherwise, nd_getset() will have built the reply to
+ * be sent - but that doesn't imply success! In some
+ * cases, the reply it's built will have a non-zero
+ * error code in it (e.g. EPERM if not superuser).
+ * So, we also drop out in that case ...
+ */
+ DPRINTF(1, (CE_WARN,
+ "unm_nd_ioctl: set %s err %d autoneg %d info %d",
+ ok ? "OK" : "FAIL", iocp->ioc_error,
+ adapter->nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val,
+ adapter->nd_params[PARAM_ADV_AUTONEG_CAP].ndp_info));
+ if (!ok)
+ return (IOC_INVAL);
+ if (iocp->ioc_error)
+ return (IOC_REPLY);
+
+ return (IOC_RESTART_REPLY);
+ }
+}
+
+/* Free the Named Dispatch Table by calling nd_free */
+void
+unm_nd_cleanup(unm_adapter *adapter)
+{
+ nd_free(&adapter->nd_data_p);
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_nic.h b/usr/src/uts/common/io/ntxn/unm_nic.h
new file mode 100644
index 0000000000..6c8232757f
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic.h
@@ -0,0 +1,819 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _UNM_NIC_
+#define _UNM_NIC_
+
+#include <sys/inttypes.h>
+#include <sys/rwlock.h>
+#include <sys/mutex.h>
+#include <sys/ddi.h>
+
+#include <sys/sunddi.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/dlpi.h>
+#include <sys/devops.h>
+#include <sys/stat.h>
+#include <sys/pci.h>
+#include <sys/note.h>
+#include <sys/modctl.h>
+#include <sys/kstat.h>
+#include <sys/ethernet.h>
+#include <sys/errno.h>
+#include <netinet/ip6.h>
+#include <inet/common.h>
+#include <sys/pattr.h>
+#include <inet/mi.h>
+#include <inet/nd.h>
+
+#include <sys/mac.h>
+#include <sys/mac_ether.h>
+#include <sys/miiregs.h> /* by fjlite out of intel */
+
+#include "unm_nic_hw.h"
+#include "nic_cmn.h"
+#include "unm_inc.h" /* For MAX_RCV_CTX */
+#include "unm_brdcfg.h"
+#include "unm_version.h"
+#include "nic_phan_reg.h"
+#include "unm_nic_ioctl.h"
+
+#define MAX_ADDR_LEN 6
+
+#define ADDR_IN_WINDOW1(off) \
+ ((off > UNM_CRB_PCIX_HOST2) && (off < UNM_CRB_MAX)) ? 1 : 0
+
+typedef unsigned long uptr_t;
+
+#define FIRST_PAGE_GROUP_START 0
+#define FIRST_PAGE_GROUP_END 0x100000
+
+#define SECOND_PAGE_GROUP_START 0x6000000
+#define SECOND_PAGE_GROUP_END 0x68BC000
+
+#define THIRD_PAGE_GROUP_START 0x70E4000
+#define THIRD_PAGE_GROUP_END 0x8000000
+
+#define FIRST_PAGE_GROUP_SIZE FIRST_PAGE_GROUP_END - FIRST_PAGE_GROUP_START
+#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
+#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
+
+/*
+ * normalize a 64MB crb address to 32MB PCI window
+ * To use CRB_NORMALIZE, window _must_ be set to 1
+ */
+#define CRB_NORMAL(reg) \
+ (reg) - UNM_CRB_PCIX_HOST2 + UNM_CRB_PCIX_HOST
+#define CRB_NORMALIZE(adapter, reg) \
+ (void *)(unsigned long)(pci_base_offset(adapter, CRB_NORMAL(reg)))
+
+#define DB_NORMALIZE(adapter, off) \
+ (void *)((unsigned long)adapter->ahw.db_base + (off))
+
+#define find_diff_among(a, b, range) \
+ ((a) < (b)?((b)-(a)):((b)+(range)-(a)))
+
+#define __FUNCTION__ __func__
+#define nx_msleep(_msecs_) delay(drv_usectohz(_msecs_ * 1000))
+
+#define HOST_TO_LE_64 LE_64
+#define HOST_TO_LE_32 LE_32
+#define LE_TO_HOST_32 LE_32
+#define HOST_TO_LE_16 LE_16
+#define LE_TO_HOST_16 LE_16
+
+#define dbwritel(DATA, ADDRESS) \
+ ddi_put32(adapter->db_handle, (uint32_t *)(ADDRESS), (DATA))
+
+/*
+ * Following macros require the mapped addresses to access
+ * the Phantom memory.
+ */
+#define UNM_NIC_PCI_READ_8(ADDRESS) \
+ ddi_get8(adapter->regs_handle, (uint8_t *)(ADDRESS))
+#define UNM_NIC_PCI_READ_16(ADDRESS) \
+ ddi_get16(adapter->regs_handle, (uint16_t *)(ADDRESS))
+#define UNM_NIC_PCI_READ_32(ADDRESS) \
+ ddi_get32(adapter->regs_handle, (uint32_t *)(ADDRESS))
+#define UNM_NIC_PCI_READ_64(ADDRESS) \
+ ddi_get64(adapter->regs_handle, (uint64_t *)(ADDRESS))
+
+#define UNM_NIC_PCI_WRITE_8(DATA, ADDRESS) \
+ ddi_put8(adapter->regs_handle, (uint8_t *)(ADDRESS), (DATA))
+#define UNM_NIC_PCI_WRITE_16(DATA, ADDRESS) \
+ ddi_put16(adapter->regs_handle, (uint16_t *)(ADDRESS), (DATA))
+#define UNM_NIC_PCI_WRITE_32(DATA, ADDRESS) \
+ ddi_put32(adapter->regs_handle, (uint32_t *)(ADDRESS), (DATA))
+#define UNM_NIC_PCI_WRITE_64(DATA, ADDRESS) \
+ ddi_put64(adapter->regs_handle, (uint64_t *)(ADDRESS), (DATA))
+
+#ifdef DEBUG_LEVEL
+#define DPRINTF(n, args) if (DEBUG_LEVEL > (n)) cmn_err args;
+#else
+#define DPRINTF(n, args)
+#endif
+
+#define UNM_SPIN_LOCK(_lp_) mutex_enter((_lp_))
+#define UNM_SPIN_UNLOCK(_lp_) mutex_exit((_lp_))
+#define UNM_SPIN_LOCK_ISR(_lp_) mutex_enter((_lp_))
+#define UNM_SPIN_UNLOCK_ISR(_lp_) mutex_exit((_lp_))
+
+#define UNM_WRITE_LOCK(_lp_) rw_enter((_lp_), RW_WRITER)
+#define UNM_WRITE_UNLOCK(_lp_) rw_exit((_lp_))
+#define UNM_READ_LOCK(_lp_) rw_enter((_lp_), RW_READER)
+#define UNM_READ_UNLOCK(_lp_) rw_exit((_lp_))
+#define UNM_WRITE_LOCK_IRQS(_lp_, _fl_) rw_enter((_lp_), RW_WRITER)
+#define UNM_WRITE_UNLOCK_IRQR(_lp_, _fl_) rw_exit((_lp_))
+
+extern char unm_nic_driver_name[];
+extern int verbmsg;
+
+typedef struct unm_dmah_node {
+ struct unm_dmah_node *next;
+ ddi_dma_handle_t dmahdl;
+}unm_dmah_node_t;
+
+typedef struct dma_area {
+ ddi_acc_handle_t acc_hdl; /* handle for memory */
+ ddi_dma_handle_t dma_hdl; /* DMA handle */
+ uint32_t ncookies;
+ u64 dma_addr;
+ void *vaddr;
+} dma_area_t;
+
+struct unm_cmd_buffer {
+ dma_area_t dma_area;
+ mblk_t *msg;
+ unm_dmah_node_t *head, *tail;
+};
+
+typedef struct pkt_info {
+ uint32_t total_len;
+ uint16_t mblk_no;
+ uint16_t etype;
+ uint16_t mac_hlen;
+ uint16_t ip_hlen;
+ uint16_t l4_proto;
+} pktinfo_t;
+
+typedef struct unm_rcv_desc_context_s unm_rcv_desc_ctx_t;
+typedef struct unm_adapter_s unm_adapter;
+
+typedef struct unm_rx_buffer {
+ struct unm_rx_buffer *next;
+ dma_area_t dma_info;
+ frtn_t rx_recycle; /* recycle function */
+ mblk_t *mp;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ unm_adapter *adapter;
+}unm_rx_buffer_t;
+
+/* Board types */
+#define UNM_NIC_GBE 0x01
+#define UNM_NIC_XGBE 0x02
+
+/*
+ * One hardware_context{} per adapter
+ * contains interrupt info as well shared hardware info.
+ */
+typedef struct _hardware_context {
+ unsigned long pci_base0;
+ unsigned long pci_len0;
+ unsigned long pci_base1;
+ unsigned long pci_len1;
+ unsigned long pci_base2;
+ unsigned long pci_len2;
+ unsigned long first_page_group_end;
+ unsigned long first_page_group_start;
+ uint8_t revision_id;
+ uint8_t cut_through;
+ uint16_t board_type;
+ int pci_func;
+ uint16_t max_ports;
+ unm_board_info_t boardcfg;
+ uint32_t linkup;
+
+ struct unm_adapter_s *adapter;
+ cmdDescType0_t *cmdDescHead;
+
+ uint32_t cmdProducer;
+ uint32_t cmdConsumer;
+ uint32_t rcvFlag;
+ uint32_t crb_base;
+ unsigned long db_base; /* base of mapped db memory */
+ unsigned long db_len; /* length of mapped db memory */
+
+
+ uint64_t cmdDesc_physAddr;
+ int qdr_sn_window, ddr_mn_window;
+ unsigned long mn_win_crb, ms_win_crb;
+ ddi_dma_handle_t cmd_desc_dma_handle;
+ ddi_acc_handle_t cmd_desc_acc_handle;
+ ddi_dma_cookie_t cmd_desc_dma_cookie;
+} hardware_context, *phardware_context;
+
+#define NX_CT_DEFAULT_RX_BUF_LEN 2048
+#define MTU_SIZE 1500
+#define MAX_COOKIES_PER_CMD 16
+#define UNM_DB_MAPSIZE_BYTES 0x1000
+#define EXTRA_HANDLES 512
+#define UNM_TX_BCOPY_THRESHOLD 128
+#define UNM_RX_BCOPY_THRESHOLD 128
+#define NX_MIN_DRIVER_RDS_SIZE 64
+
+typedef struct unm_pauseparam {
+ uint16_t rx_pause;
+ uint16_t tx_pause;
+} unm_pauseparam_t;
+
+/*
+ * The driver supports the NDD ioctls ND_GET/ND_SET, and the loopback
+ * ioctls LB_GET_INFO_SIZE/LB_GET_INFO/LB_GET_MODE/LB_SET_MODE
+ *
+ * These are the values to use with LD_SET_MODE.
+ */
+#define UNM_LOOP_NONE 0
+#define UNM_LOOP_INTERNAL_PHY 1
+#define UNM_LOOP_INTERNAL_MAC 2
+
+/*
+ * Named Data (ND) Parameter Management Structure
+ */
+typedef struct {
+ int ndp_info;
+ int ndp_min;
+ int ndp_max;
+ int ndp_val;
+ char *ndp_name;
+} nd_param_t; /* 0x18 (24) bytes */
+
+/*
+ * NDD parameter indexes, divided into:
+ *
+ * read-only parameters describing the hardware's capabilities
+ * read-write parameters controlling the advertised capabilities
+ * read-only parameters describing the partner's capabilities
+ * read-only parameters describing the link state
+ */
+enum {
+ PARAM_AUTONEG_CAP = 0,
+ PARAM_PAUSE_CAP,
+ PARAM_ASYM_PAUSE_CAP,
+ PARAM_10000FDX_CAP,
+ PARAM_1000FDX_CAP,
+ PARAM_1000HDX_CAP,
+ PARAM_100T4_CAP,
+ PARAM_100FDX_CAP,
+ PARAM_100HDX_CAP,
+ PARAM_10FDX_CAP,
+ PARAM_10HDX_CAP,
+
+ PARAM_ADV_AUTONEG_CAP,
+ PARAM_ADV_PAUSE_CAP,
+ PARAM_ADV_ASYM_PAUSE_CAP,
+ PARAM_ADV_10000FDX_CAP,
+ PARAM_ADV_1000FDX_CAP,
+ PARAM_ADV_1000HDX_CAP,
+ PARAM_ADV_100T4_CAP,
+ PARAM_ADV_100FDX_CAP,
+ PARAM_ADV_100HDX_CAP,
+ PARAM_ADV_10FDX_CAP,
+ PARAM_ADV_10HDX_CAP,
+
+ PARAM_LINK_STATUS,
+ PARAM_LINK_SPEED,
+ PARAM_LINK_DUPLEX,
+
+ PARAM_LOOP_MODE,
+
+ PARAM_COUNT
+};
+
+struct unm_adapter_stats {
+ uint64_t rcvdbadmsg;
+ uint64_t xmitcalled;
+ uint64_t xmitedframes;
+ uint64_t xmitfinished;
+ uint64_t badmsglen;
+ uint64_t nocmddescriptor;
+ uint64_t polled;
+ uint64_t uphappy;
+ uint64_t updropped;
+ uint64_t uplcong;
+ uint64_t uphcong;
+ uint64_t upmcong;
+ uint64_t updunno;
+ uint64_t msgfreed;
+ uint64_t txdropped;
+ uint64_t txnullmsg;
+ uint64_t csummed;
+ uint64_t no_rcv;
+ uint64_t rxbytes;
+ uint64_t txbytes;
+ uint64_t ints;
+ uint64_t desballocfailed;
+ uint64_t txcopyed;
+ uint64_t txmapped;
+ uint64_t outoftxdmahdl;
+ uint64_t outofcmddesc;
+ uint64_t rxcopyed;
+ uint64_t rxmapped;
+ uint64_t outofrxbuf;
+ uint64_t promiscmode;
+ uint64_t rxbufshort;
+ uint64_t allocbfailed;
+};
+
+/* descriptor types */
+#define RCV_RING_STD RCV_DESC_NORMAL
+#define RCV_RING_JUMBO RCV_DESC_JUMBO
+#define RCV_RING_LRO RCV_DESC_LRO
+
+/*
+ * Rcv Descriptor Context. One such per Rcv Descriptor. There may
+ * be one Rcv Descriptor for normal packets, one for jumbo,
+ * one for LRO and may be expanded.
+ */
+struct unm_rcv_desc_context_s {
+ uint32_t producer;
+
+ uint64_t phys_addr;
+ dev_info_t *phys_pdev;
+ /* address of rx ring in Phantom */
+ rcvDesc_t *desc_head;
+
+ uint32_t MaxRxDescCount;
+ uint32_t rx_desc_handled;
+ uint32_t rx_buf_card;
+ uint32_t rx_buf_total;
+ uint32_t rx_buf_free;
+ uint32_t rx_buf_recycle;
+ unm_rx_buffer_t *rx_buf_pool;
+ unm_rx_buffer_t *pool_list;
+ unm_rx_buffer_t *recycle_list;
+ kmutex_t pool_lock[1]; /* buffer pool lock */
+ kmutex_t recycle_lock[1]; /* buffer recycle lock */
+ /* size of the receive buf */
+ uint32_t buf_size;
+ /* rx buffers for receive */
+
+ ddi_dma_handle_t rx_desc_dma_handle;
+ ddi_acc_handle_t rx_desc_acc_handle;
+ ddi_dma_cookie_t rx_desc_dma_cookie;
+ uint32_t host_rx_producer;
+ uint32_t dma_size;
+};
+
+/*
+ * Receive context. There is one such structure per instance of the
+ * receive processing. Any state information that is relevant to
+ * the receive, and is must be in this structure. The global data may be
+ * present elsewhere.
+ */
+typedef struct unm_recv_context_s {
+ unm_rcv_desc_ctx_t rcv_desc[NUM_RCV_DESC_RINGS];
+
+ uint32_t statusRxConsumer;
+
+ uint64_t rcvStatusDesc_physAddr;
+ statusDesc_t *rcvStatusDescHead;
+
+ ddi_dma_handle_t status_desc_dma_handle;
+ ddi_acc_handle_t status_desc_acc_handle;
+ ddi_dma_cookie_t status_desc_dma_cookie;
+
+ uint32_t state, host_sds_consumer;
+ uint16_t context_id, virt_port;
+} unm_recv_context_t;
+
+#define UNM_NIC_MSI_ENABLED 0x02
+#define UNM_NIC_MSIX_ENABLED 0x04
+#define UNM_IS_MSI_FAMILY(ADAPTER) \
+ ((ADAPTER)->flags & (UNM_NIC_MSI_ENABLED | UNM_NIC_MSIX_ENABLED))
+
+#define NX_USE_MSIX
+
+/* msix defines */
+#define MSIX_ENTRIES_PER_ADAPTER 8
+#define UNM_MSIX_TBL_SPACE 8192
+#define UNM_PCI_REG_MSIX_TBL 0x44
+
+/*
+ * Bug: word or char write on MSI-X capcabilities register (0x40) in PCI config
+ * space has no effect on register values. Need to write dword.
+ */
+#define UNM_HWBUG_8_WORKAROUND
+
+/*
+ * Bug: Can not reset bit 32 (msix enable bit) on MSI-X capcabilities
+ * register (0x40) independently.
+ * Need to write 0x0 (zero) to MSI-X capcabilities register in order to reset
+ * msix enable bit. On writing zero rest of the bits are not touched.
+ */
+#define UNM_HWBUG_9_WORKAROUND
+
+#define UNM_MC_COUNT 38 /* == ((UNM_ADDR_L2LU_COUNT-1)/4) -2 */
+
+/* Following structure is for specific port information */
+struct unm_adapter_s {
+ hardware_context ahw;
+ uint8_t id[32];
+ uint16_t portnum;
+ uint16_t physical_port;
+ uint16_t link_speed;
+ uint16_t link_duplex;
+
+ struct unm_adapter_stats stats;
+ int rx_csum;
+ int status;
+ kmutex_t stats_lock;
+ unsigned char mac_addr[MAX_ADDR_LEN];
+ int mtu; /* active mtu */
+ int maxmtu; /* max possible mtu value */
+ uint32_t promisc;
+
+ mac_resource_handle_t mac_rx_ring_ha;
+ mac_handle_t mach;
+ int flags;
+
+ int instance;
+ dev_info_t *dip;
+ ddi_acc_handle_t pci_cfg_handle;
+ ddi_acc_handle_t regs_handle;
+ ddi_dma_attr_t gc_dma_attr_desc;
+
+ struct ddi_device_acc_attr gc_attr_desc;
+ ddi_iblock_cookie_t iblock_cookie;
+ const char *name;
+ ddi_acc_handle_t db_handle;
+
+ ddi_intr_handle_t intr_handle;
+ int intr_type;
+ uint_t intr_pri;
+ unm_dmah_node_t *dmahdl_pool;
+ unm_dmah_node_t tx_dma_hdls[MAX_CMD_DESCRIPTORS+EXTRA_HANDLES];
+ uint64_t freehdls;
+ uint64_t freecmds;
+ int tx_bcopy_threshold;
+ kmutex_t tx_lock;
+ krwlock_t adapter_lock;
+ kmutex_t lock;
+ struct nx_legacy_intr_set legacy_intr;
+ timeout_id_t watchdog_timer;
+ kstat_t *kstats[1];
+
+ uint32_t curr_window;
+ uint32_t crb_win;
+ uint32_t cmdProducer;
+ uint32_t *cmdConsumer;
+
+ uint32_t interrupt_crb;
+ uint32_t fw_major;
+ uint32_t crb_addr_cmd_producer;
+ uint32_t crb_addr_cmd_consumer;
+ uint16_t tx_context_id;
+ short context_alloced;
+ int max_rds_rings;
+
+ uint32_t lastCmdConsumer;
+ /* Num of bufs posted in phantom */
+ uint32_t pendingCmdCount;
+ uint32_t MaxTxDescCount;
+ uint32_t MaxRxDescCount;
+ uint32_t MaxJumboRxDescCount;
+ uint32_t MaxLroRxDescCount;
+ /* Num of instances active on cmd buffer ring */
+ int resched_needed;
+
+ int driver_mismatch;
+ uint32_t temp;
+
+ struct unm_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */
+ int rx_bcopy_threshold;
+
+ /*
+ * Receive instances. These can be either one per port,
+ * or one per peg, etc.
+ */
+ unm_recv_context_t recv_ctx[MAX_RCV_CTX];
+ int is_up;
+
+ /* context interface shared between card and host */
+ RingContext *ctxDesc;
+ uint64_t ctxDesc_physAddr;
+ ddi_dma_handle_t ctxDesc_dma_handle;
+ ddi_acc_handle_t ctxDesc_acc_handle;
+
+ struct {
+ void *addr;
+ uint64_t phys_addr;
+ ddi_dma_handle_t dma_handle;
+ ddi_acc_handle_t acc_handle;
+ } dummy_dma;
+
+ void (*unm_nic_pci_change_crbwindow)(struct unm_adapter_s *,
+ uint32_t);
+ int (*unm_crb_writelit_adapter)(struct unm_adapter_s *,
+ unsigned long, int);
+ unsigned long long
+ (*unm_nic_pci_set_window)(struct unm_adapter_s *,
+ unsigned long long);
+ int (*unm_nic_fill_statistics)(struct unm_adapter_s *,
+ struct unm_statistics *);
+ int (*unm_nic_clear_statistics)(struct unm_adapter_s *);
+ int (*unm_nic_hw_write_wx)(struct unm_adapter_s *, u64,
+ void *, int);
+ int (*unm_nic_hw_read_wx)(struct unm_adapter_s *, u64, void *, int);
+ int (*unm_nic_hw_write_ioctl)(struct unm_adapter_s *, u64, void *,
+ int);
+ int (*unm_nic_hw_read_ioctl)(struct unm_adapter_s *, u64, void *,
+ int);
+ int (*unm_nic_pci_mem_write)(struct unm_adapter_s *, u64, void *,
+ int);
+ int (*unm_nic_pci_mem_read)(struct unm_adapter_s *, u64, void *,
+ int);
+ int (*unm_nic_pci_write_immediate)(struct unm_adapter_s *, u64,
+ u32 *);
+ int (*unm_nic_pci_read_immediate)(struct unm_adapter_s *, u64,
+ u32 *);
+ void (*unm_nic_pci_write_normalize)(struct unm_adapter_s *, u64,
+ u32);
+ u32 (*unm_nic_pci_read_normalize)(struct unm_adapter_s *, u64);
+
+ caddr_t nd_data_p;
+ nd_param_t nd_params[PARAM_COUNT];
+}; /* unm_adapter structure */
+
+#define UNM_HOST_DUMMY_DMA_SIZE 1024
+
+/* Following structure is for specific port information */
+
+#define PCI_OFFSET_FIRST_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base0 + off)
+#define PCI_OFFSET_SECOND_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START)
+#define PCI_OFFSET_THIRD_RANGE(adapter, off) \
+ ((adapter)->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START)
+
+#define pci_base_offset(adapter, off) \
+ ((((off) < ((adapter)->ahw.first_page_group_end)) && \
+ ((off) >= ((adapter)->ahw.first_page_group_start))) ? \
+ ((adapter)->ahw.pci_base0 + (off)) : \
+ ((((off) < SECOND_PAGE_GROUP_END) && \
+ ((off) >= SECOND_PAGE_GROUP_START)) ? \
+ ((adapter)->ahw.pci_base1 + \
+ (off) - SECOND_PAGE_GROUP_START) : \
+ ((((off) < THIRD_PAGE_GROUP_END) && \
+ ((off) >= THIRD_PAGE_GROUP_START)) ? \
+ ((adapter)->ahw.pci_base2 + (off) - \
+ THIRD_PAGE_GROUP_START) : \
+ 0)))
+#define unm_nic_reg_write(_adp_, _off_, _val_) \
+ { \
+ __uint32_t _v1_ = (_val_); \
+ ((_adp_)->unm_nic_hw_write_wx((_adp_), (_off_), \
+ &_v1_, 4)); \
+ }
+
+#define unm_nic_reg_read(_adp_, _off_, _ptr_) \
+ ((_adp_)->unm_nic_hw_read_wx((_adp_), (_off_), (_ptr_), 4))
+
+
+#define unm_nic_write_w0(_adp_, _idx_, _val_) \
+ ((_adp_)->unm_nic_hw_write_wx((_adp_), (_idx_), &(_val_), 4))
+
+#define unm_nic_read_w0(_adp_, _idx_, _val_) \
+ ((_adp_)->unm_nic_hw_read_wx((_adp_), (_idx_), (_val_), 4))
+
+/* Functions available from unm_nic_hw.c */
+int unm_nic_get_board_info(struct unm_adapter_s *adapter);
+void _unm_nic_write_crb(struct unm_adapter_s *adapter, uint32_t index,
+ uint32_t value);
+void unm_nic_write_crb(struct unm_adapter_s *adapter, uint32_t index,
+ uint32_t value);
+void _unm_nic_read_crb(struct unm_adapter_s *adapter, uint32_t index,
+ uint32_t *value);
+void unm_nic_read_crb(struct unm_adapter_s *adapter, uint32_t index,
+ uint32_t *value);
+// int unm_nic_reg_read (unm_adapter *adapter, u64 off);
+int _unm_nic_hw_write(struct unm_adapter_s *adapter,
+ u64 off, void *data, int len);
+int unm_nic_hw_write(struct unm_adapter_s *adapter,
+ u64 off, void *data, int len);
+int _unm_nic_hw_read(struct unm_adapter_s *adapter,
+ u64 off, void *data, int len);
+int unm_nic_hw_read(struct unm_adapter_s *adapter,
+ u64 off, void *data, int len);
+void _unm_nic_hw_block_read(struct unm_adapter_s *adapter,
+ u64 off, void *data, int num_words);
+void unm_nic_hw_block_read(struct unm_adapter_s *adapter,
+ u64 off, void *data, int num_words);
+void _unm_nic_hw_block_write(struct unm_adapter_s *adapter,
+ u64 off, void *data, int num_words);
+void unm_nic_hw_block_write(struct unm_adapter_s *adapter,
+ u64 off, void *data, int num_words);
+int unm_nic_pci_mem_write(struct unm_adapter_s *adapter,
+ u64 off, void *data, int size);
+void unm_nic_mem_block_read(struct unm_adapter_s *adapter, u64 off,
+ void *data, int num_words);
+void unm_nic_mem_block_write(struct unm_adapter_s *adapter, u64 off,
+ void *data, int num_words);
+int unm_nic_hw_read_ioctl(unm_adapter *adapter, u64 off, void *data, int len);
+int unm_nic_hw_write_ioctl(unm_adapter *adapter, u64 off, void *data, int len);
+int unm_nic_macaddr_set(struct unm_adapter_s *, __uint8_t *addr);
+void unm_tcl_resetall(struct unm_adapter_s *adapter);
+void unm_tcl_phaninit(struct unm_adapter_s *adapter);
+void unm_tcl_postimage(struct unm_adapter_s *adapter);
+int unm_nic_set_mtu(struct unm_adapter_s *adapter, int new_mtu);
+long unm_nic_phy_read(unm_adapter *adapter, long reg, __uint32_t *);
+long unm_nic_init_port(struct unm_adapter_s *adapter);
+void unm_crb_write_adapter(unsigned long off, void *data,
+ struct unm_adapter_s *adapter);
+int unm_crb_read_adapter(unsigned long off, void *data,
+ struct unm_adapter_s *adapter);
+int unm_crb_read_val_adapter(unsigned long off,
+ struct unm_adapter_s *adapter);
+void unm_nic_stop_port(struct unm_adapter_s *adapter);
+int unm_nic_set_promisc_mode(struct unm_adapter_s *adapter);
+int unm_nic_unset_promisc_mode(struct unm_adapter_s *adapter);
+
+/* unm_nic_hw.c */
+void unm_nic_pci_change_crbwindow_128M(unm_adapter *adapter, uint32_t wndw);
+int unm_crb_writelit_adapter_128M(struct unm_adapter_s *, unsigned long, int);
+int unm_nic_hw_write_wx_128M(unm_adapter *adapter, u64 off, void *data,
+ int len);
+int unm_nic_hw_read_wx_128M(unm_adapter *adapter, u64 off, void *data, int len);
+int unm_nic_hw_write_ioctl_128M(unm_adapter *adapter, u64 off, void *data,
+ int len);
+int unm_nic_hw_read_ioctl_128M(unm_adapter *adapter, u64 off, void *data,
+ int len);
+int unm_nic_pci_mem_write_128M(struct unm_adapter_s *adapter, u64 off,
+ void *data, int size);
+int unm_nic_pci_mem_read_128M(struct unm_adapter_s *adapter, u64 off,
+ void *data, int size);
+void unm_nic_pci_write_normalize_128M(unm_adapter *adapter, u64 off, u32 data);
+u32 unm_nic_pci_read_normalize_128M(unm_adapter *adapter, u64 off);
+int unm_nic_pci_write_immediate_128M(unm_adapter *adapter, u64 off, u32 *data);
+int unm_nic_pci_read_immediate_128M(unm_adapter *adapter, u64 off, u32 *data);
+unsigned long long unm_nic_pci_set_window_128M(unm_adapter *adapter,
+ unsigned long long addr);
+int unm_nic_clear_statistics_128M(struct unm_adapter_s *adapter);
+int unm_nic_fill_statistics_128M(struct unm_adapter_s *adapter,
+ struct unm_statistics *unm_stats);
+
+void unm_nic_pci_change_crbwindow_2M(unm_adapter *adapter, uint32_t wndw);
+int unm_crb_writelit_adapter_2M(struct unm_adapter_s *, unsigned long, int);
+int unm_nic_hw_write_wx_2M(unm_adapter *adapter, u64 off, void *data, int len);
+int unm_nic_pci_mem_write_2M(struct unm_adapter_s *adapter, u64 off,
+ void *data, int size);
+int unm_nic_pci_mem_read_2M(struct unm_adapter_s *adapter, u64 off,
+ void *data, int size);
+int unm_nic_hw_read_wx_2M(unm_adapter *adapter, u64 off, void *data, int len);
+void unm_nic_pci_write_normalize_2M(unm_adapter *adapter, u64 off, u32 data);
+u32 unm_nic_pci_read_normalize_2M(unm_adapter *adapter, u64 off);
+int unm_nic_pci_write_immediate_2M(unm_adapter *adapter, u64 off, u32 *data);
+int unm_nic_pci_read_immediate_2M(unm_adapter *adapter, u64 off, u32 *data);
+unsigned long long unm_nic_pci_set_window_2M(unm_adapter *adapter,
+ unsigned long long addr);
+int unm_nic_clear_statistics_2M(struct unm_adapter_s *adapter);
+int unm_nic_fill_statistics_2M(struct unm_adapter_s *adapter,
+ struct unm_statistics *unm_stats);
+void nx_p3_nic_set_multi(unm_adapter *adapter);
+
+/* unm_nic_init.c */
+int phantom_init(struct unm_adapter_s *adapter, int first_time);
+int load_from_flash(struct unm_adapter_s *adapter);
+int pinit_from_rom(unm_adapter *adapter, int verbose);
+int rom_fast_read(struct unm_adapter_s *adapter, int addr, int *valp);
+
+/* unm_nic_isr.c */
+void unm_nic_handle_phy_intr(unm_adapter *adapter);
+
+/* niu.c */
+native_t unm_niu_set_promiscuous_mode(struct unm_adapter_s *adapter,
+ unm_niu_prom_mode_t mode);
+native_t unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s *adapter,
+ unm_niu_prom_mode_t mode);
+
+int unm_niu_xg_macaddr_set(struct unm_adapter_s *adapter,
+ unm_ethernet_macaddr_t addr);
+native_t unm_niu_disable_xg_port(struct unm_adapter_s *adapter);
+
+long unm_niu_gbe_init_port(long port);
+native_t unm_niu_enable_gbe_port(struct unm_adapter_s *adapter,
+ unm_niu_gbe_ifmode_t mode);
+native_t unm_niu_disable_gbe_port(struct unm_adapter_s *adapter);
+
+int unm_niu_macaddr_get(struct unm_adapter_s *adapter, unsigned char *addr);
+int unm_niu_macaddr_set(struct unm_adapter_s *adapter,
+ unm_ethernet_macaddr_t addr);
+
+int unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable);
+int unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s *adapter, int enable);
+int unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable);
+long unm_niu_gbe_disable_phy_interrupts(struct unm_adapter_s *);
+long unm_niu_gbe_phy_read(struct unm_adapter_s *,
+ long reg, unm_crbword_t *readval);
+
+/* unm_nic_ctx.c */
+int netxen_create_rxtx(struct unm_adapter_s *adapter);
+void netxen_destroy_rxtx(struct unm_adapter_s *adapter);
+int nx_fw_cmd_set_mtu(struct unm_adapter_s *adapter, int mtu);
+
+/* unm_nic_main.c */
+int receive_peg_ready(struct unm_adapter_s *adapter);
+void unm_nic_update_cmd_producer(struct unm_adapter_s *adapter,
+ uint32_t crb_producer);
+void unm_desc_dma_sync(ddi_dma_handle_t handle, uint_t start, uint_t count,
+ uint_t range, uint_t unit_size, uint_t direction);
+int unm_pci_alloc_consistent(unm_adapter *, int, caddr_t *,
+ ddi_dma_cookie_t *, ddi_dma_handle_t *, ddi_acc_handle_t *);
+void unm_pci_free_consistent(ddi_dma_handle_t *, ddi_acc_handle_t *);
+
+/* unm_ndd.c */
+int unm_nd_init(unm_adapter *adapter);
+enum ioc_reply unm_nd_ioctl(unm_adapter *adapter, queue_t *wq,
+ mblk_t *mp, struct iocblk *iocp);
+void unm_nd_cleanup(unm_adapter *adapter);
+
+/* unm_gem.c */
+void unm_destroy_intr(unm_adapter *adapter);
+void unm_free_dummy_dma(unm_adapter *adapter);
+
+/*
+ * (Internal) return values from ioctl subroutines
+ */
+enum ioc_reply {
+ IOC_INVAL = -1, /* bad, NAK with EINVAL */
+ IOC_DONE, /* OK, reply sent */
+ IOC_ACK, /* OK, just send ACK */
+ IOC_REPLY, /* OK, just send reply */
+ IOC_RESTART_ACK, /* OK, restart & ACK */
+ IOC_RESTART_REPLY /* OK, restart & reply */
+};
+
+/*
+ * Shorthand for the NDD parameters
+ */
+#define param_adv_autoneg nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val
+#define param_adv_pause nd_params[PARAM_ADV_PAUSE_CAP].ndp_val
+#define param_adv_asym_pause nd_params[PARAM_ADV_ASYM_PAUSE_CAP].ndp_val
+#define param_adv_10000fdx nd_params[PARAM_ADV_10000FDX_CAP].ndp_val
+#define param_adv_1000fdx nd_params[PARAM_ADV_1000FDX_CAP].ndp_val
+#define param_adv_1000hdx nd_params[PARAM_ADV_1000HDX_CAP].ndp_val
+#define param_adv_100fdx nd_params[PARAM_ADV_100FDX_CAP].ndp_val
+#define param_adv_100hdx nd_params[PARAM_ADV_100HDX_CAP].ndp_val
+#define param_adv_10fdx nd_params[PARAM_ADV_10FDX_CAP].ndp_val
+#define param_adv_10hdx nd_params[PARAM_ADV_10HDX_CAP].ndp_val
+#define param_link_up nd_params[PARAM_LINK_STATUS].ndp_val
+#define param_link_speed nd_params[PARAM_LINK_SPEED].ndp_val
+#define param_link_duplex nd_params[PARAM_LINK_DUPLEX].ndp_val
+#define param_loop_mode nd_params[PARAM_LOOP_MODE].ndp_val
+
+/*
+ * Property lookups
+ */
+#define UNM_PROP_EXISTS(d, n) \
+ ddi_prop_exists(DDI_DEV_T_ANY, (d), DDI_PROP_DONTPASS, (n))
+#define UNM_PROP_GET_INT(d, n) \
+ ddi_prop_get_int(DDI_DEV_T_ANY, (d), DDI_PROP_DONTPASS, (n), -1)
+
+/*
+ * Bit flags in the 'debug' word ...
+ */
+#define UNM_DBG_TRACE 0x00000002 /* general flow tracing */
+#define UNM_DBG_NDD 0x20000000 /* NDD operations */
+
+#define MBPS_10 10
+#define MBPS_100 100
+#define MBPS_1000 1000
+
+#endif /* !_UNM_NIC_ */
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_ctx.c b/usr/src/uts/common/io/ntxn/unm_nic_ctx.c
new file mode 100644
index 0000000000..863920991c
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_ctx.c
@@ -0,0 +1,655 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+#include <sys/pci.h>
+
+#include "unm_nic_hw.h"
+#include "unm_nic.h"
+#include "nic_phan_reg.h"
+#include "nic_cmn.h"
+
+typedef unsigned int nx_rcode_t;
+
+#include "nx_errorcode.h"
+#include "nxhal_nic_interface.h"
+
+#define NXHAL_VERSION 1
+
+#define NX_OS_CRB_RETRY_COUNT 4000
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+#define NX_CDRP_CMD_GET_STATISTICS 0x0000000f
+#define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010
+#define NX_CDRP_CMD_SET_MTU 0x00000012
+#define NX_CDRP_CMD_MAX 0x00000013
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+/*
+ * Context state
+ */
+#define NX_HOST_CTX_STATE_FREED 0
+#define NX_HOST_CTX_STATE_ALLOCATED 1
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+static int
+netxen_api_lock(struct unm_adapter_s *adapter)
+{
+ u32 done = 0, timeout = 0;
+
+ for (;;) {
+ /* Acquire PCIE HW semaphore5 */
+ unm_nic_read_w0(adapter,
+ UNM_PCIE_REG(PCIE_SEM5_LOCK), &done);
+
+ if (done == 1)
+ break;
+
+ if (++timeout >= NX_OS_CRB_RETRY_COUNT) {
+ cmn_err(CE_WARN, "%s: lock timeout.\n", __func__);
+ return (-1);
+ }
+
+ drv_usecwait(1000);
+ }
+
+#if 0
+ unm_nic_reg_write(adapter, NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
+#endif
+ return (0);
+}
+
+static void
+netxen_api_unlock(struct unm_adapter_s *adapter)
+{
+ u32 val;
+
+ /* Release PCIE HW semaphore5 */
+ unm_nic_read_w0(adapter,
+ UNM_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+}
+
+static u32
+netxen_poll_rsp(struct unm_adapter_s *adapter)
+{
+ u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ int timeout = 0;
+
+ do {
+ /* give atleast 1ms for firmware to respond */
+ drv_usecwait(1000);
+
+ if (++timeout > NX_OS_CRB_RETRY_COUNT)
+ return (NX_CDRP_RSP_TIMEOUT);
+
+ adapter->unm_nic_hw_read_wx(adapter, NX_CDRP_CRB_OFFSET,
+ &raw_rsp, 4);
+
+ rsp = LE_TO_HOST_32(raw_rsp);
+ } while (!NX_CDRP_IS_RSP(rsp));
+
+ return (rsp);
+}
+
+static u32
+netxen_issue_cmd(struct unm_adapter_s *adapter,
+ u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+{
+ u32 rsp;
+ u32 signature = 0;
+ u32 rcode = NX_RCODE_SUCCESS;
+
+ signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
+
+ /* Acquire semaphore before accessing CRB */
+ if (netxen_api_lock(adapter))
+ return (NX_RCODE_TIMEOUT);
+
+ unm_nic_reg_write(adapter, NX_SIGN_CRB_OFFSET,
+ HOST_TO_LE_32(signature));
+
+ unm_nic_reg_write(adapter, NX_ARG1_CRB_OFFSET,
+ HOST_TO_LE_32(arg1));
+
+ unm_nic_reg_write(adapter, NX_ARG2_CRB_OFFSET,
+ HOST_TO_LE_32(arg2));
+
+ unm_nic_reg_write(adapter, NX_ARG3_CRB_OFFSET,
+ HOST_TO_LE_32(arg3));
+
+ unm_nic_reg_write(adapter, NX_CDRP_CRB_OFFSET,
+ HOST_TO_LE_32(NX_CDRP_FORM_CMD(cmd)));
+
+ rsp = netxen_poll_rsp(adapter);
+
+ if (rsp == NX_CDRP_RSP_TIMEOUT) {
+ cmn_err(CE_WARN, "%s: card response timeout.\n",
+ unm_nic_driver_name);
+
+ rcode = NX_RCODE_TIMEOUT;
+ } else if (rsp == NX_CDRP_RSP_FAIL) {
+ adapter->unm_nic_hw_read_wx(adapter, NX_ARG1_CRB_OFFSET,
+ &rcode, 4);
+ rcode = LE_TO_HOST_32(rcode);
+
+ cmn_err(CE_WARN, "%s: failed card response code:0x%x\n",
+ unm_nic_driver_name, rcode);
+ }
+
+ /* Release semaphore */
+ netxen_api_unlock(adapter);
+
+ return (rcode);
+}
+
+int
+nx_fw_cmd_set_mtu(struct unm_adapter_s *adapter, int mtu)
+{
+ u32 rcode = NX_RCODE_SUCCESS;
+ struct unm_recv_context_s *recv_ctx = &adapter->recv_ctx[0];
+
+ if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
+ rcode = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ mtu,
+ 0,
+ NX_CDRP_CMD_SET_MTU);
+
+ if (rcode != NX_RCODE_SUCCESS)
+ return (-EIO);
+
+ return (0);
+}
+
+static int
+nx_fw_cmd_create_rx_ctx(struct unm_adapter_s *adapter)
+{
+ unm_recv_context_t *recv_ctx = &adapter->recv_ctx[0];
+ nx_hostrq_rx_ctx_t *prq;
+ nx_cardrsp_rx_ctx_t *prsp;
+ nx_hostrq_rds_ring_t *prq_rds;
+ nx_hostrq_sds_ring_t *prq_sds;
+ nx_cardrsp_rds_ring_t *prsp_rds;
+ nx_cardrsp_sds_ring_t *prsp_sds;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ ddi_dma_cookie_t cookie;
+ ddi_dma_handle_t rqdhdl, rsdhdl;
+ ddi_acc_handle_t rqahdl, rsahdl;
+ uint64_t hostrq_phys_addr, cardrsp_phys_addr;
+ u64 phys_addr;
+ u32 cap, reg;
+ size_t rq_size, rsp_size;
+ void *addr;
+ int i, nrds_rings, nsds_rings, err;
+
+ /* only one sds ring for now */
+ nrds_rings = adapter->max_rds_rings;
+ nsds_rings = 1;
+
+ rq_size =
+ SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
+ rsp_size =
+ SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
+
+ if (unm_pci_alloc_consistent(adapter, rq_size, (caddr_t *)&addr,
+ &cookie, &rqdhdl, &rqahdl) != DDI_SUCCESS)
+ return (-ENOMEM);
+ hostrq_phys_addr = cookie.dmac_laddress;
+ prq = (nx_hostrq_rx_ctx_t *)addr;
+
+ if (unm_pci_alloc_consistent(adapter, rsp_size, (caddr_t *)&addr,
+ &cookie, &rsdhdl, &rsahdl) != DDI_SUCCESS) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ cardrsp_phys_addr = cookie.dmac_laddress;
+ prsp = (nx_cardrsp_rx_ctx_t *)addr;
+
+ prq->host_rsp_dma_addr = HOST_TO_LE_64(cardrsp_phys_addr);
+
+ cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+ cap |= (NX_CAP0_JUMBO_CONTIGUOUS);
+
+ prq->capabilities[0] = HOST_TO_LE_32(cap);
+ prq->host_int_crb_mode =
+ HOST_TO_LE_32(NX_HOST_INT_CRB_MODE_SHARED);
+ prq->host_rds_crb_mode =
+ HOST_TO_LE_32(NX_HOST_RDS_CRB_MODE_UNIQUE);
+
+ prq->num_rds_rings = HOST_TO_LE_16(nrds_rings);
+ prq->num_sds_rings = HOST_TO_LE_16(nsds_rings);
+ prq->rds_ring_offset = 0;
+ prq->sds_ring_offset = prq->rds_ring_offset +
+ (sizeof (nx_hostrq_rds_ring_t) * nrds_rings);
+
+ prq_rds = (nx_hostrq_rds_ring_t *)(uintptr_t)(prq->data +
+ prq->rds_ring_offset);
+
+ for (i = 0; i < nrds_rings; i++) {
+ rcv_desc = &recv_ctx->rcv_desc[i];
+
+ prq_rds[i].host_phys_addr = HOST_TO_LE_64(rcv_desc->phys_addr);
+ prq_rds[i].ring_size = HOST_TO_LE_32(rcv_desc->MaxRxDescCount);
+ prq_rds[i].ring_kind = HOST_TO_LE_32(i);
+ prq_rds[i].buff_size = HOST_TO_LE_64(rcv_desc->dma_size);
+ }
+
+ prq_sds = (nx_hostrq_sds_ring_t *)(uintptr_t)(prq->data +
+ prq->sds_ring_offset);
+
+ prq_sds[0].host_phys_addr =
+ HOST_TO_LE_64(recv_ctx->rcvStatusDesc_physAddr);
+ prq_sds[0].ring_size = HOST_TO_LE_32(adapter->MaxRxDescCount);
+ /* only one msix vector for now */
+ prq_sds[0].msi_index = HOST_TO_LE_32(0);
+
+ /* now byteswap offsets */
+ prq->rds_ring_offset = HOST_TO_LE_32(prq->rds_ring_offset);
+ prq->sds_ring_offset = HOST_TO_LE_32(prq->sds_ring_offset);
+
+ phys_addr = hostrq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ (u32)(phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_RX_CTX);
+ if (err) {
+ cmn_err(CE_WARN, "Failed to create rx ctx in firmware%d\n",
+ err);
+ goto out_free_rsp;
+ }
+
+
+ prsp_rds = ((nx_cardrsp_rds_ring_t *)(uintptr_t)
+ &prsp->data[prsp->rds_ring_offset]);
+
+ for (i = 0; i < LE_TO_HOST_32(prsp->num_rds_rings); i++) {
+ rcv_desc = &recv_ctx->rcv_desc[i];
+
+ reg = LE_TO_HOST_32(prsp_rds[i].host_producer_crb);
+ rcv_desc->host_rx_producer = UNM_NIC_REG(reg - 0x200);
+ }
+
+ prsp_sds = ((nx_cardrsp_sds_ring_t *)(uintptr_t)
+ &prsp->data[prsp->sds_ring_offset]);
+ reg = LE_TO_HOST_32(prsp_sds[0].host_consumer_crb);
+ recv_ctx->host_sds_consumer = UNM_NIC_REG(reg - 0x200);
+
+ reg = LE_TO_HOST_32(prsp_sds[0].interrupt_crb);
+ adapter->interrupt_crb = UNM_NIC_REG(reg - 0x200);
+
+ recv_ctx->state = LE_TO_HOST_32(prsp->host_ctx_state);
+ recv_ctx->context_id = LE_TO_HOST_16(prsp->context_id);
+ recv_ctx->virt_port = LE_TO_HOST_16(prsp->virt_port);
+
+out_free_rsp:
+ unm_pci_free_consistent(&rsdhdl, &rsahdl);
+out_free_rq:
+ unm_pci_free_consistent(&rqdhdl, &rqahdl);
+ return (err);
+}
+
+static void
+nx_fw_cmd_destroy_rx_ctx(struct unm_adapter_s *adapter)
+{
+ struct unm_recv_context_s *recv_ctx = &adapter->recv_ctx[0];
+
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_RX_CTX)) {
+
+ cmn_err(CE_WARN, "%s: Failed to destroy rx ctx in firmware\n",
+ unm_nic_driver_name);
+ }
+}
+
+static int
+nx_fw_cmd_create_tx_ctx(struct unm_adapter_s *adapter)
+{
+ nx_hostrq_tx_ctx_t *prq;
+ nx_hostrq_cds_ring_t *prq_cds;
+ nx_cardrsp_tx_ctx_t *prsp;
+ ddi_dma_cookie_t cookie;
+ ddi_dma_handle_t rqdhdl, rsdhdl;
+ ddi_acc_handle_t rqahdl, rsahdl;
+ void *rq_addr, *rsp_addr;
+ size_t rq_size, rsp_size;
+ u32 temp;
+ int err = 0;
+ u64 offset, phys_addr;
+ uint64_t rq_phys_addr, rsp_phys_addr;
+
+ rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
+ if (unm_pci_alloc_consistent(adapter, rq_size, (caddr_t *)&rq_addr,
+ &cookie, &rqdhdl, &rqahdl) != DDI_SUCCESS)
+ return (-ENOMEM);
+ rq_phys_addr = cookie.dmac_laddress;
+
+ rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
+ if (unm_pci_alloc_consistent(adapter, rsp_size, (caddr_t *)&rsp_addr,
+ &cookie, &rsdhdl, &rsahdl) != DDI_SUCCESS) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ rsp_phys_addr = cookie.dmac_laddress;
+
+ (void) memset(rq_addr, 0, rq_size);
+ prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+
+ (void) memset(rsp_addr, 0, rsp_size);
+ prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+
+ prq->host_rsp_dma_addr = HOST_TO_LE_64(rsp_phys_addr);
+
+ temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+ prq->capabilities[0] = HOST_TO_LE_32(temp);
+
+ prq->host_int_crb_mode =
+ HOST_TO_LE_32(NX_HOST_INT_CRB_MODE_SHARED);
+
+ prq->interrupt_ctl = 0;
+ prq->msi_index = 0;
+
+ prq->dummy_dma_addr = HOST_TO_LE_64(adapter->dummy_dma.phys_addr);
+
+ offset = adapter->ctxDesc_physAddr + sizeof (RingContext);
+ prq->cmd_cons_dma_addr = HOST_TO_LE_64(offset);
+
+ prq_cds = &prq->cds_ring;
+
+ prq_cds->host_phys_addr =
+ HOST_TO_LE_64(adapter->ahw.cmdDesc_physAddr);
+
+ prq_cds->ring_size = HOST_TO_LE_32(adapter->MaxTxDescCount);
+
+ phys_addr = rq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ ((u32)phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_TX_CTX);
+
+ if (err == NX_RCODE_SUCCESS) {
+ temp = LE_TO_HOST_32(prsp->cds_ring.host_producer_crb);
+ adapter->crb_addr_cmd_producer =
+ UNM_NIC_REG(temp - 0x200);
+#if 0
+ adapter->tx_state =
+ LE_TO_HOST_32(prsp->host_ctx_state);
+#endif
+ adapter->tx_context_id =
+ LE_TO_HOST_16(prsp->context_id);
+ } else {
+ cmn_err(CE_WARN, "Failed to create tx ctx in firmware%d\n",
+ err);
+ err = -EIO;
+ }
+
+ unm_pci_free_consistent(&rsdhdl, &rsahdl);
+
+out_free_rq:
+ unm_pci_free_consistent(&rqdhdl, &rqahdl);
+
+ return (err);
+}
+
+static void
+nx_fw_cmd_destroy_tx_ctx(struct unm_adapter_s *adapter)
+{
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ adapter->tx_context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_TX_CTX)) {
+
+ cmn_err(CE_WARN, "%s: Failed to destroy tx ctx in firmware\n",
+ unm_nic_driver_name);
+ }
+}
+
+static u64 ctx_addr_sig_regs[][3] = {
+ {UNM_NIC_REG(0x188), UNM_NIC_REG(0x18c), UNM_NIC_REG(0x1c0)},
+ {UNM_NIC_REG(0x190), UNM_NIC_REG(0x194), UNM_NIC_REG(0x1c4)},
+ {UNM_NIC_REG(0x198), UNM_NIC_REG(0x19c), UNM_NIC_REG(0x1c8)},
+ {UNM_NIC_REG(0x1a0), UNM_NIC_REG(0x1a4), UNM_NIC_REG(0x1cc)}
+};
+
+#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
+#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
+#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
+
+struct netxen_recv_crb {
+ u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
+ u32 crb_sts_consumer;
+};
+
+static struct netxen_recv_crb recv_crb_registers[] = {
+ /* Instance 0 */
+ {
+ /* crb_rcv_producer: */
+ {
+ UNM_NIC_REG(0x100),
+ /* Jumbo frames */
+ UNM_NIC_REG(0x110),
+ /* LRO */
+ UNM_NIC_REG(0x120)
+ },
+ /* crb_sts_consumer: */
+ UNM_NIC_REG(0x138),
+ },
+ /* Instance 1 */
+ {
+ /* crb_rcv_producer: */
+ {
+ UNM_NIC_REG(0x144),
+ /* Jumbo frames */
+ UNM_NIC_REG(0x154),
+ /* LRO */
+ UNM_NIC_REG(0x164)
+ },
+ /* crb_sts_consumer: */
+ UNM_NIC_REG(0x17c),
+ },
+ /* Instance 2 */
+ {
+ /* crb_rcv_producer: */
+ {
+ UNM_NIC_REG(0x1d8),
+ /* Jumbo frames */
+ UNM_NIC_REG(0x1f8),
+ /* LRO */
+ UNM_NIC_REG(0x208)
+ },
+ /* crb_sts_consumer: */
+ UNM_NIC_REG(0x220),
+ },
+ /* Instance 3 */
+ {
+ /* crb_rcv_producer: */
+ {
+ UNM_NIC_REG(0x22c),
+ /* Jumbo frames */
+ UNM_NIC_REG(0x23c),
+ /* LRO */
+ UNM_NIC_REG(0x24c)
+ },
+ /* crb_sts_consumer: */
+ UNM_NIC_REG(0x264),
+ },
+};
+
+static uint32_t sw_int_mask[4] = {
+ CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
+ CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
+};
+
+static int
+netxen_init_old_ctx(struct unm_adapter_s *adapter)
+{
+ hardware_context *hw = &adapter->ahw;
+ struct unm_recv_context_s *recv_ctx;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ int ctx, ring, func_id = adapter->portnum;
+ unsigned int temp;
+
+ adapter->ctxDesc->CmdRingAddrLo = hw->cmdDesc_physAddr & 0xffffffffUL;
+ adapter->ctxDesc->CmdRingAddrHi = ((U64)hw->cmdDesc_physAddr >> 32);
+ adapter->ctxDesc->CmdRingSize = adapter->MaxTxDescCount;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+
+ adapter->ctxDesc->RcvContext[ring].RcvRingAddrLo =
+ rcv_desc->phys_addr & 0xffffffffUL;
+ adapter->ctxDesc->RcvContext[ring].RcvRingAddrHi =
+ ((U64)rcv_desc->phys_addr>>32);
+ adapter->ctxDesc->RcvContext[ring].RcvRingSize =
+ rcv_desc->MaxRxDescCount;
+
+ rcv_desc->host_rx_producer =
+ recv_crb_registers[adapter->portnum].
+ crb_rcv_producer[ring];
+ }
+
+ adapter->ctxDesc->StsRingAddrLo =
+ recv_ctx->rcvStatusDesc_physAddr & 0xffffffff;
+ adapter->ctxDesc->StsRingAddrHi =
+ recv_ctx->rcvStatusDesc_physAddr >> 32;
+ adapter->ctxDesc->StsRingSize = adapter->MaxRxDescCount;
+
+ recv_ctx->host_sds_consumer =
+ recv_crb_registers[adapter->portnum].crb_sts_consumer;
+ }
+
+ adapter->interrupt_crb = sw_int_mask[adapter->portnum];
+
+ temp = lower32(adapter->ctxDesc_physAddr);
+ adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_ADDR_REG_LO(func_id),
+ &temp, 4);
+ temp = upper32(adapter->ctxDesc_physAddr);
+ adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_ADDR_REG_HI(func_id),
+ &temp, 4);
+ temp = UNM_CTX_SIGNATURE | func_id;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_CTX_SIGNATURE_REG(func_id),
+ &temp, 4);
+
+ return (0);
+}
+
+void
+netxen_destroy_rxtx(struct unm_adapter_s *adapter)
+{
+ if (adapter->fw_major >= 4) {
+ nx_fw_cmd_destroy_tx_ctx(adapter);
+ nx_fw_cmd_destroy_rx_ctx(adapter);
+ }
+}
+
+int
+netxen_create_rxtx(struct unm_adapter_s *adapter)
+{
+ int err;
+
+ if (adapter->fw_major >= 4) {
+ err = nx_fw_cmd_create_rx_ctx(adapter);
+ if (err)
+ return (err);
+ err = nx_fw_cmd_create_tx_ctx(adapter);
+ if (err)
+ nx_fw_cmd_destroy_rx_ctx(adapter);
+ return (err);
+ } else {
+ return (netxen_init_old_ctx(adapter));
+ }
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_hw.c b/usr/src/uts/common/io/ntxn/unm_nic_hw.c
new file mode 100644
index 0000000000..297f883991
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_hw.c
@@ -0,0 +1,2204 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+
+#include <sys/pci.h>
+
+#include "unm_nic.h"
+#include "unm_nic_hw.h"
+#include "nic_cmn.h"
+#include "unm_brdcfg.h"
+#include "driver_info.h"
+
+long unm_niu_gbe_phy_read(struct unm_adapter_s *,
+ long reg, unm_crbword_t *readval);
+
+#define MASK(n) ((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | \
+ ((addr >> 25) & 0x3ff)) // 64K?
+#define MS_WIN(addr) (addr & 0x0ffc0000)
+#define UNM_PCI_MN_2M (0)
+#define UNM_PCI_MS_2M (0x80000)
+#define UNM_PCI_OCM0_2M (0xc0000)
+#define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800)
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+
+#define CRB_BLK(off) ((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
+#define CRB_WINDOW_2M (0x130060)
+#define UNM_PCI_CAMQM_2M_END (0x04800800UL)
+#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define UNM_PCI_CAMQM_2M_BASE (0x000ff800UL)
+#define CRB_INDIRECT_2M (0x1e0000UL)
+
+static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+ {{{0, 0, 0, 0}}}, /* 0: PCI */
+ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
+ {1, 0x0110000, 0x0120000, 0x130000},
+ {1, 0x0120000, 0x0122000, 0x124000},
+ {1, 0x0130000, 0x0132000, 0x126000},
+ {1, 0x0140000, 0x0142000, 0x128000},
+ {1, 0x0150000, 0x0152000, 0x12a000},
+ {1, 0x0160000, 0x0170000, 0x110000},
+ {1, 0x0170000, 0x0172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x01e0000, 0x01e0800, 0x122000},
+ {0, 0x0000000, 0x0000000, 0x000000}}},
+ {{{1, 0x0200000, 0x0210000, 0x180000}}}, /* 2: MN */
+ {{{0, 0, 0, 0}}}, /* 3: */
+ {{{1, 0x0400000, 0x0401000, 0x169000}}}, /* 4: P2NR1 */
+ {{{1, 0x0500000, 0x0510000, 0x140000}}}, /* 5: SRE */
+ {{{1, 0x0600000, 0x0610000, 0x1c0000}}}, /* 6: NIU */
+ {{{1, 0x0700000, 0x0704000, 0x1b8000}}}, /* 7: QM */
+ {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x08f0000, 0x08f2000, 0x172000}}},
+ {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x09f0000, 0x09f2000, 0x176000}}},
+ {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0af0000, 0x0af2000, 0x17a000}}},
+ {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0bf0000, 0x0bf2000, 0x17e000}}},
+ {{{1, 0x0c00000, 0x0c04000, 0x1d4000}}}, /* 12: I2Q */
+ {{{1, 0x0d00000, 0x0d04000, 0x1a4000}}}, /* 13: TMR */
+ {{{1, 0x0e00000, 0x0e04000, 0x1a0000}}}, /* 14: ROMUSB */
+ {{{1, 0x0f00000, 0x0f01000, 0x164000}}}, /* 15: PEG4 */
+ {{{0, 0x1000000, 0x1004000, 0x1a8000}}}, /* 16: XDMA */
+ {{{1, 0x1100000, 0x1101000, 0x160000}}}, /* 17: PEG0 */
+ {{{1, 0x1200000, 0x1201000, 0x161000}}}, /* 18: PEG1 */
+ {{{1, 0x1300000, 0x1301000, 0x162000}}}, /* 19: PEG2 */
+ {{{1, 0x1400000, 0x1401000, 0x163000}}}, /* 20: PEG3 */
+ {{{1, 0x1500000, 0x1501000, 0x165000}}}, /* 21: P2ND */
+ {{{1, 0x1600000, 0x1601000, 0x166000}}}, /* 22: P2NI */
+ {{{0, 0, 0, 0}}}, /* 23: */
+ {{{0, 0, 0, 0}}}, /* 24: */
+ {{{0, 0, 0, 0}}}, /* 25: */
+ {{{0, 0, 0, 0}}}, /* 26: */
+ {{{0, 0, 0, 0}}}, /* 27: */
+ {{{0, 0, 0, 0}}}, /* 28: */
+ {{{1, 0x1d00000, 0x1d10000, 0x190000}}}, /* 29: MS */
+ {{{1, 0x1e00000, 0x1e01000, 0x16a000}}}, /* 30: P2NR2 */
+ {{{1, 0x1f00000, 0x1f10000, 0x150000}}}, /* 31: EPG */
+ {{{0}}}, /* 32: PCI */
+ {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
+ {1, 0x2110000, 0x2120000, 0x130000},
+ {1, 0x2120000, 0x2122000, 0x124000},
+ {1, 0x2130000, 0x2132000, 0x126000},
+ {1, 0x2140000, 0x2142000, 0x128000},
+ {1, 0x2150000, 0x2152000, 0x12a000},
+ {1, 0x2160000, 0x2170000, 0x110000},
+ {1, 0x2170000, 0x2172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000}}},
+ {{{1, 0x2200000, 0x2204000, 0x1b0000}}}, /* 34: CAM */
+ {{{0}}}, /* 35: */
+ {{{0}}}, /* 36: */
+ {{{0}}}, /* 37: */
+ {{{0}}}, /* 38: */
+ {{{0}}}, /* 39: */
+ {{{1, 0x2800000, 0x2804000, 0x1a4000}}}, /* 40: TMR */
+ {{{1, 0x2900000, 0x2901000, 0x16b000}}}, /* 41: P2NR3 */
+ {{{1, 0x2a00000, 0x2a00400, 0x1ac400}}}, /* 42: RPMX1 */
+ {{{1, 0x2b00000, 0x2b00400, 0x1ac800}}}, /* 43: RPMX2 */
+ {{{1, 0x2c00000, 0x2c00400, 0x1acc00}}}, /* 44: RPMX3 */
+ {{{1, 0x2d00000, 0x2d00400, 0x1ad000}}}, /* 45: RPMX4 */
+ {{{1, 0x2e00000, 0x2e00400, 0x1ad400}}}, /* 46: RPMX5 */
+ {{{1, 0x2f00000, 0x2f00400, 0x1ad800}}}, /* 47: RPMX6 */
+ {{{1, 0x3000000, 0x3000400, 0x1adc00}}}, /* 48: RPMX7 */
+ {{{0, 0x3100000, 0x3104000, 0x1a8000}}}, /* 49: XDMA */
+ {{{1, 0x3200000, 0x3204000, 0x1d4000}}}, /* 50: I2Q */
+ {{{1, 0x3300000, 0x3304000, 0x1a0000}}}, /* 51: ROMUSB */
+ {{{0}}}, /* 52: */
+ {{{1, 0x3500000, 0x3500400, 0x1ac000}}}, /* 53: RPMX0 */
+ {{{1, 0x3600000, 0x3600400, 0x1ae000}}}, /* 54: RPMX8 */
+ {{{1, 0x3700000, 0x3700400, 0x1ae400}}}, /* 55: RPMX9 */
+ {{{1, 0x3800000, 0x3804000, 0x1d0000}}}, /* 56: OCM0 */
+ {{{1, 0x3900000, 0x3904000, 0x1b4000}}}, /* 57: CRYPTO */
+ {{{1, 0x3a00000, 0x3a04000, 0x1d8000}}}, /* 58: SMB */
+ {{{0}}}, /* 59: I2C0 */
+ {{{0}}}, /* 60: I2C1 */
+ {{{1, 0x3d00000, 0x3d04000, 0x1d8000}}}, /* 61: LPC */
+ {{{1, 0x3e00000, 0x3e01000, 0x167000}}}, /* 62: P2NC */
+ {{{1, 0x3f00000, 0x3f01000, 0x168000}}} /* 63: P2NR0 */
+};
+
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+static unsigned crb_hub_agt[64] = {
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_PS,
+ UNM_HW_CRB_HUB_AGT_ADR_MN,
+ UNM_HW_CRB_HUB_AGT_ADR_MS,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_SRE,
+ UNM_HW_CRB_HUB_AGT_ADR_NIU,
+ UNM_HW_CRB_HUB_AGT_ADR_QMN,
+ UNM_HW_CRB_HUB_AGT_ADR_SQN0,
+ UNM_HW_CRB_HUB_AGT_ADR_SQN1,
+ UNM_HW_CRB_HUB_AGT_ADR_SQN2,
+ UNM_HW_CRB_HUB_AGT_ADR_SQN3,
+ UNM_HW_CRB_HUB_AGT_ADR_I2Q,
+ UNM_HW_CRB_HUB_AGT_ADR_TIMR,
+ UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ UNM_HW_CRB_HUB_AGT_ADR_PGN4,
+ UNM_HW_CRB_HUB_AGT_ADR_XDMA,
+ UNM_HW_CRB_HUB_AGT_ADR_PGN0,
+ UNM_HW_CRB_HUB_AGT_ADR_PGN1,
+ UNM_HW_CRB_HUB_AGT_ADR_PGN2,
+ UNM_HW_CRB_HUB_AGT_ADR_PGN3,
+ UNM_HW_CRB_HUB_AGT_ADR_PGND,
+ UNM_HW_CRB_HUB_AGT_ADR_PGNI,
+ UNM_HW_CRB_HUB_AGT_ADR_PGS0,
+ UNM_HW_CRB_HUB_AGT_ADR_PGS1,
+ UNM_HW_CRB_HUB_AGT_ADR_PGS2,
+ UNM_HW_CRB_HUB_AGT_ADR_PGS3,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_PGSI,
+ UNM_HW_CRB_HUB_AGT_ADR_SN,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_EG,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_PS,
+ UNM_HW_CRB_HUB_AGT_ADR_CAM,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_TIMR,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX1,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX2,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX3,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX4,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX5,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX6,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX7,
+ UNM_HW_CRB_HUB_AGT_ADR_XDMA,
+ UNM_HW_CRB_HUB_AGT_ADR_I2Q,
+ UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX0,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX8,
+ UNM_HW_CRB_HUB_AGT_ADR_RPMX9,
+ UNM_HW_CRB_HUB_AGT_ADR_OCM0,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_SMB,
+ UNM_HW_CRB_HUB_AGT_ADR_I2C0,
+ UNM_HW_CRB_HUB_AGT_ADR_I2C1,
+ 0,
+ UNM_HW_CRB_HUB_AGT_ADR_PGNC,
+ 0,
+};
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+
+static void
+crb_win_lock(struct unm_adapter_s *adapter)
+{
+ int i;
+ int done = 0, timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore3 from PCI HW block */
+ adapter->unm_nic_hw_read_wx(adapter,
+ UNM_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+ if (done == 1)
+ break;
+ if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
+ cmn_err(CE_WARN, "%s%d: crb_win_lock timed out\n",
+ adapter->name, adapter->instance);
+ return;
+ }
+ timeout++;
+ /*
+ * Yield CPU
+ */
+ for (i = 0; i < 20; i++);
+ }
+ adapter->unm_crb_writelit_adapter(adapter, UNM_CRB_WIN_LOCK_ID,
+ adapter->portnum);
+}
+
+static void
+crb_win_unlock(struct unm_adapter_s *adapter)
+{
+ int val;
+
+ adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_SEM7_UNLOCK),
+ &val, 4);
+}
+
+/*
+ * Changes the CRB window to the specified window.
+ */
+void
+unm_nic_pci_change_crbwindow_128M(unm_adapter *adapter, uint32_t wndw)
+{
+ unm_pcix_crb_window_t window;
+ unsigned long offset;
+ uint32_t tmp;
+
+ if (adapter->curr_window == wndw) {
+ return;
+ }
+
+ /*
+ * Move the CRB window.
+ * We need to write to the "direct access" region of PCI
+ * to avoid a race condition where the window register has
+ * not been successfully written across CRB before the target
+ * register address is received by PCI. The direct region bypasses
+ * the CRB bus.
+ */
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ UNM_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(adapter->ahw.pci_func)));
+
+ *(unm_crbword_t *)&window = 0;
+ window.addrbit = wndw;
+ UNM_NIC_PCI_WRITE_32(*(unsigned int *)&window, (void*) (offset));
+ /* MUST make sure window is set before we forge on... */
+ while ((tmp = UNM_NIC_PCI_READ_32((void*) offset)) !=
+ *(uint32_t *)&window) {
+ cmn_err(CE_WARN, "%s: %s WARNING: CRB window value not "
+ "registered properly: 0x%08x.\n",
+ unm_nic_driver_name, __FUNCTION__, tmp);
+ }
+
+ adapter->curr_window = wndw;
+}
+
+
+/*
+ * Changes the CRB window to the specified window.
+ */
+/* ARGSUSED */
+void
+unm_nic_pci_change_crbwindow_2M(unm_adapter *adapter, uint32_t wndw)
+{
+}
+
+
+uint32_t
+unm_nic_get_crbwindow(unm_adapter *adapter)
+{
+ return (adapter->curr_window);
+}
+
+/*
+ * Return -1 if off is not valid,
+ * 1 if window access is needed. 'off' is set to offset from
+ * CRB space in 128M pci map
+ * 0 if no window access is needed. 'off' is set to 2M addr
+ * In: 'off' is offset from base in 128M pci map
+ */
+int
+unm_nic_pci_get_crb_addr_2M(unm_adapter *adapter, u64 *off, int len)
+{
+ unsigned long end = *off + len;
+ crb_128M_2M_sub_block_map_t *m;
+
+
+ if (*off >= UNM_CRB_MAX)
+ return (-1);
+
+ if (*off >= UNM_PCI_CAMQM && (end <= UNM_PCI_CAMQM_2M_END)) {
+ *off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE +
+ adapter->ahw.pci_base0;
+ return (0);
+ }
+
+ if (*off < UNM_PCI_CRBSPACE)
+ return (-1);
+
+ *off -= UNM_PCI_CRBSPACE;
+ end = *off + len;
+ /*
+ * Try direct map
+ */
+
+ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+ if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+ *off = *off + m->start_2M - m->start_128M +
+ adapter->ahw.pci_base0;
+ return (0);
+ }
+
+ /*
+ * Not in direct map, use crb window
+ */
+ return (1);
+}
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+unm_nic_pci_set_crbwindow_2M(unm_adapter *adapter, u64 *off)
+{
+ u32 win_read;
+
+ adapter->crb_win = CRB_HI(*off);
+ UNM_NIC_PCI_WRITE_32(adapter->crb_win, (void *) (CRB_WINDOW_2M +
+ adapter->ahw.pci_base0));
+ /*
+ * Read back value to make sure write has gone through before trying
+ * to use it.
+ */
+ win_read = UNM_NIC_PCI_READ_32((void *)
+ (CRB_WINDOW_2M + adapter->ahw.pci_base0));
+ if (win_read != adapter->crb_win) {
+ cmn_err(CE_WARN, "%s: Written crbwin (0x%x) != Read crbwin "
+ "(0x%x), off=0x%llx\n", __FUNCTION__, adapter->crb_win,
+ win_read, *off);
+ }
+ *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+ adapter->ahw.pci_base0;
+}
+
+int
+unm_nic_hw_write_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ void *addr;
+ u64 offset = off;
+
+ if (ADDR_IN_WINDOW1(off)) { // Window 1
+ addr = CRB_NORMALIZE(adapter, off);
+ if (!addr) {
+ offset = CRB_NORMAL(off);
+ if (adapter->ahw.pci_len0 == 0)
+ offset -= UNM_PCI_CRBSPACE;
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
+ offset);
+ }
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
+ if (!addr) {
+ offset = off;
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
+ offset);
+ }
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+ }
+
+ switch (len) {
+ case 1:
+ UNM_NIC_PCI_WRITE_8 (*(__uint8_t *)data, addr);
+ break;
+ case 2:
+ UNM_NIC_PCI_WRITE_16 (*(__uint16_t *)data, addr);
+ break;
+ case 4:
+ UNM_NIC_PCI_WRITE_32 (*(__uint32_t *)data, addr);
+ break;
+ case 8:
+ UNM_NIC_PCI_WRITE_64 (*(__uint64_t *)data, addr);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_WRITE_64(data, addr, (len>>3));
+ break;
+ }
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+/*
+ * Note : 'len' argument should be either 1, 2, 4, or a multiple of 8.
+ */
+int
+unm_nic_hw_write_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ /*
+ * This is modified from _unm_nic_hw_write().
+ * unm_nic_hw_write does not exist now.
+ */
+
+ void *addr;
+
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ addr = CRB_NORMALIZE(adapter, off);
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+ }
+
+
+ if (!addr) {
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+ return (1);
+ }
+
+ switch (len) {
+ case 1:
+ UNM_NIC_PCI_WRITE_8 (*(__uint8_t *)data, addr);
+ break;
+ case 2:
+ UNM_NIC_PCI_WRITE_16 (*(__uint16_t *)data, addr);
+ break;
+ case 4:
+ UNM_NIC_PCI_WRITE_32 (*(__uint32_t *)data, addr);
+ break;
+ case 8:
+ UNM_NIC_PCI_WRITE_64 (*(__uint64_t *)data, addr);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN,
+ "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_WRITE_64(data, addr, (len>>3));
+ break;
+ }
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+void
+unm_nic_pci_write_normalize_128M(unm_adapter *adapter, u64 off, u32 data)
+{
+ UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
+}
+
+/*
+ * Note : only 32-bit reads!
+ */
+u32
+unm_nic_pci_read_normalize_128M(unm_adapter *adapter, u64 off)
+{
+ return (UNM_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, off)));
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int
+unm_nic_pci_write_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
+{
+ UNM_NIC_PCI_WRITE_32(*data,
+ (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
+ return (0);
+}
+
+/*
+ * Note : only 32-bit reads!
+ */
+int
+unm_nic_pci_read_immediate_128M(unm_adapter *adapter, u64 off, u32 *data)
+{
+ *data = UNM_NIC_PCI_READ_32((void *)
+ (uptr_t)(pci_base_offset(adapter, off)));
+ return (0);
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+void
+unm_nic_pci_write_normalize_2M(unm_adapter *adapter, u64 off, u32 data)
+{
+ u32 temp = data;
+
+ adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
+}
+
+/*
+ * Note : only 32-bit reads!
+ */
+u32
+unm_nic_pci_read_normalize_2M(unm_adapter *adapter, u64 off)
+{
+ u32 temp;
+
+ adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
+
+ return (temp);
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int
+unm_nic_pci_write_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
+{
+ u32 temp = *data;
+
+ adapter->unm_nic_hw_write_wx(adapter, off, &temp, 4);
+
+ return (0);
+}
+
+/*
+ * Note : only 32-bit reads!
+ */
+int
+unm_nic_pci_read_immediate_2M(unm_adapter *adapter, u64 off, u32 *data)
+{
+ u32 temp;
+
+ adapter->unm_nic_hw_read_wx(adapter, off, &temp, 4);
+
+ *data = temp;
+
+ return (0);
+}
+
+/*
+ * write cross hw window boundary is not supported
+ * 'len' should be either 1, 2, 4, or multiple of 8
+ */
+int
+unm_nic_hw_write_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ int rv;
+
+ rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
+ __FUNCTION__, off);
+ return (-1);
+ }
+
+ if (rv == 1) {
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ unm_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
+
+ switch (len) {
+ case 1:
+ UNM_NIC_PCI_WRITE_8(*(__uint8_t *)data, (void *) (uptr_t)off);
+ break;
+ case 2:
+ UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, (void *) (uptr_t)off);
+ break;
+ case 4:
+ UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, (void *) (uptr_t)off);
+ break;
+ case 8:
+ UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, (void *) (uptr_t)off);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_WRITE_64(data, (uptr_t)off, (len>>3));
+ break;
+ }
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+int
+unm_nic_hw_read_ioctl_128M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ void *addr;
+ u64 offset;
+
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ addr = CRB_NORMALIZE(adapter, off);
+ if (!addr) {
+ offset = CRB_NORMAL(off);
+ if (adapter->ahw.pci_len0 == 0)
+ offset -= UNM_PCI_CRBSPACE;
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
+ offset);
+ }
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
+ if (!addr) {
+ offset = off;
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 +
+ offset);
+ }
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+ }
+
+ switch (len) {
+ case 1:
+ *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
+ break;
+ case 2:
+ *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
+ break;
+ case 4:
+ *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
+ break;
+ case 8:
+ *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
+ break;
+ }
+
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+int
+unm_nic_hw_read_wx_2M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ int rv;
+
+ rv = unm_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ cmn_err(CE_PANIC, "%s: invalid offset: 0x%016llx\n",
+ __FUNCTION__, off);
+ return (-1);
+ }
+
+ if (rv == 1) {
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ unm_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
+
+ switch (len) {
+ case 1:
+ *(__uint8_t *)data = UNM_NIC_PCI_READ_8((void *) (uptr_t)off);
+ break;
+ case 2:
+ *(__uint16_t *)data = UNM_NIC_PCI_READ_16((void *) (uptr_t)off);
+ break;
+ case 4:
+ *(__uint32_t *)data = UNM_NIC_PCI_READ_32((void *) (uptr_t)off);
+ break;
+ case 8:
+ *(__uint64_t *)data = UNM_NIC_PCI_READ_64((void *) (uptr_t)off);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN, "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_READ_64(data, (void *) (uptr_t)off, (len>>3));
+ break;
+ }
+
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+int
+unm_nic_hw_read_wx_128M(unm_adapter *adapter, u64 off, void *data, int len)
+{
+ void *addr;
+
+ if (ADDR_IN_WINDOW1(off)) {
+ // Window 1
+ addr = CRB_NORMALIZE(adapter, off);
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, off));
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+ }
+
+ if (!addr) {
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+ return (1);
+ }
+
+ switch (len) {
+ case 1:
+ *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
+ break;
+ case 2:
+ *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
+ break;
+ case 4:
+ *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
+ break;
+ case 8:
+ *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
+ break;
+ default:
+#if !defined(NDEBUG)
+ if ((len & 0x7) != 0)
+ cmn_err(CE_WARN,
+ "%s: %s len(%d) not multiple of 8.\n",
+ unm_nic_driver_name, __FUNCTION__, len);
+#endif
+ UNM_NIC_HW_BLOCK_READ_64(data, addr, (len>>3));
+ break;
+ }
+
+ if (ADDR_IN_WINDOW1(off)) {// Window 1
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {// Window 0
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+/* PCI Windowing for DDR regions. */
+#define ADDR_IN_RANGE(addr, low, high) \
+ (((addr) <= (high)) && ((low) ? ((addr) >= (low)) : 1))
+
+/*
+ * check memory access boundary.
+ * used by test agent. support ddr access only for now
+ */
+/* ARGSUSED */
+static unsigned long
+unm_nic_pci_mem_bound_check(struct unm_adapter_s *adapter,
+ unsigned long long addr, int size)
+{
+ if (!ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX) ||
+ !ADDR_IN_RANGE(addr + size -1, UNM_ADDR_DDR_NET,
+ UNM_ADDR_DDR_NET_MAX) || ((size != 1) && (size != 2) &&
+ (size != 4) && (size != 8)))
+ return (0);
+
+ return (1);
+}
+
+int unm_pci_set_window_warning_count = 0;
+
+unsigned long long
+unm_nic_pci_set_window_128M(struct unm_adapter_s *adapter,
+ unsigned long long addr)
+{
+ int window;
+ unsigned long long qdr_max;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ qdr_max = NX_P2_ADDR_QDR_NET_MAX;
+ } else {
+ qdr_max = NX_P3_ADDR_QDR_NET_MAX;
+ }
+
+ if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ /* MN access should never come here */
+ cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
+ addr = -1ULL;
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
+ addr -= UNM_ADDR_OCM0;
+ addr += UNM_PCI_OCM0;
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
+ addr -= UNM_ADDR_OCM1;
+ addr += UNM_PCI_OCM1;
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
+ /* QDR network side */
+ addr -= UNM_ADDR_QDR_NET;
+ window = (addr >> 22) & 0x3f;
+ if (adapter->ahw.qdr_sn_window != window) {
+ adapter->ahw.qdr_sn_window = window;
+ UNM_NIC_PCI_WRITE_32((window << 22),
+ (void *) (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
+ UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
+ adapter->ahw.pci_func)))));
+ /* MUST make sure window is set before we forge on... */
+ (void) UNM_NIC_PCI_READ_32((void *)
+ (uptr_t)(PCI_OFFSET_SECOND_RANGE(adapter,
+ UNM_PCIX_PH_REG(PCIE_SN_WINDOW_REG(
+ adapter->ahw.pci_func)))));
+ }
+ addr -= (window * 0x400000);
+ addr += UNM_PCI_QDR_NET;
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((unm_pci_set_window_warning_count++ < 8) ||
+ (unm_pci_set_window_warning_count%64 == 0)) {
+ cmn_err(CE_WARN, "%s: Warning:unm_nic_pci_set_window() "
+ "Unknown address range!\n", unm_nic_driver_name);
+ }
+ addr = -1ULL;
+ }
+ return (addr);
+}
+
+unsigned long long
+unm_nic_pci_set_window_2M(struct unm_adapter_s *adapter,
+ unsigned long long addr)
+{
+ int window;
+ u32 win_read;
+
+ if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ window = MN_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
+ UNM_PCI_CRBSPACE, &window, 4);
+ adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
+ UNM_PCI_CRBSPACE, &win_read, 4);
+ if ((win_read << 17) != window) {
+ cmn_err(CE_WARN,
+ "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n",
+ __FUNCTION__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
+ unsigned int temp1;
+// OCM: pci_addr[20:18] == 011 && pci_addr[17:11] != 7f
+ if ((addr & 0x00ff800) == 0xff800) {
+ // if bits 19:18&17:11 are on
+ cmn_err(CE_WARN, "%s: QM access not handled.\n",
+ __FUNCTION__);
+ addr = -1ULL;
+ }
+
+ window = OCM_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.mn_win_crb |
+ UNM_PCI_CRBSPACE, &window, 4);
+ adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.mn_win_crb |
+ UNM_PCI_CRBSPACE, &win_read, 4);
+ temp1 = ((window & 0x1FF) << 7) |
+ ((window & 0x0FFFE0000) >> 17);
+ if (win_read != temp1) {
+ cmn_err(CE_WARN,
+ "%s: Written OCMwin(0x%x) != Read OCMwin(0x%x)\n",
+ __FUNCTION__, temp1, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
+
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
+ NX_P3_ADDR_QDR_NET_MAX)) {
+ /* QDR network side */
+ window = MS_WIN(addr);
+ adapter->ahw.qdr_sn_window = window;
+ adapter->unm_nic_hw_write_wx(adapter, adapter->ahw.ms_win_crb |
+ UNM_PCI_CRBSPACE, &window, 4);
+ adapter->unm_nic_hw_read_wx(adapter, adapter->ahw.ms_win_crb |
+ UNM_PCI_CRBSPACE, &win_read, 4);
+ if (win_read != window) {
+ cmn_err(CE_WARN,
+ "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n",
+ __FUNCTION__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
+
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((unm_pci_set_window_warning_count++ < 8) ||
+ (unm_pci_set_window_warning_count%64 == 0)) {
+ cmn_err(CE_WARN, "%s%d: %s Unknown address range!\n",
+ adapter->name, adapter->instance, __FUNCTION__);
+ }
+ addr = -1ULL;
+ }
+ return (addr);
+}
+
+/* check if address is in the same windows as the previous access */
+static unsigned long
+unm_nic_pci_is_same_window(struct unm_adapter_s *adapter,
+ unsigned long long addr)
+{
+ int window;
+ unsigned long long qdr_max;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ qdr_max = NX_P2_ADDR_QDR_NET_MAX;
+ } else {
+ qdr_max = NX_P3_ADDR_QDR_NET_MAX;
+ }
+
+ if (ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, UNM_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ /* MN access can not come here */
+ cmn_err(CE_PANIC, "%s\n", __FUNCTION__);
+#if 0
+ window = ((addr - UNM_ADDR_DDR_NET) >> 25) & 0x3ff;
+ if (adapter->ahw.ddr_mn_window == window) {
+ return (1);
+ }
+#endif
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, UNM_ADDR_OCM0_MAX)) {
+ return (1);
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, UNM_ADDR_OCM1_MAX)) {
+ return (1);
+ } else if (ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
+ /* QDR network side */
+ window = ((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f;
+ if (adapter->ahw.qdr_sn_window == window) {
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+static int
+unm_nic_pci_mem_read_direct(struct unm_adapter_s *adapter,
+ u64 off, void *data, int size)
+{
+ void *addr;
+ int ret = 0;
+ u64 start;
+
+#if 0
+ /*
+ * This check can not be currently executed, since phanmon findq
+ * command breaks this check whereby 8 byte reads are being attempted
+ * on "aligned-by-4" addresses on x86. Reason this works is our version
+ * breaks up the access into 2 consecutive 4 byte writes; on other
+ * architectures, this might require "aligned-by-8" addresses and we
+ * will run into trouble.
+ *
+ * Check alignment for expected sizes of 1, 2, 4, 8. Other size
+ * values will not trigger access.
+ */
+ if ((off & (size - 1)) != 0)
+ return (-1);
+#endif
+
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
+ (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ cmn_err(CE_WARN, "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", unm_nic_driver_name, off);
+ return (-1);
+ }
+
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
+ if (!addr)
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
+
+ switch (size) {
+ case 1:
+ *(__uint8_t *)data = UNM_NIC_PCI_READ_8(addr);
+ break;
+ case 2:
+ *(__uint16_t *)data = UNM_NIC_PCI_READ_16(addr);
+ break;
+ case 4:
+ *(__uint32_t *)data = UNM_NIC_PCI_READ_32(addr);
+ break;
+ case 8:
+ *(__uint64_t *)data = UNM_NIC_PCI_READ_64(addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ return (ret);
+}
+
+static int
+unm_nic_pci_mem_write_direct(struct unm_adapter_s *adapter, u64 off,
+ void *data, int size)
+{
+ void *addr;
+ int ret = 0;
+ u64 start;
+
+#if 0
+ /*
+ * This check can not be currently executed, since firmware load
+ * breaks this check whereby 8 byte writes are being attempted on
+ * "aligned-by-4" addresses on x86. Reason this works is our version
+ * breaks up the access into 2 consecutive 4 byte writes; on other
+ * architectures, this might require "aligned-by-8" addresses and we
+ * will run into trouble.
+ *
+ * Check alignment for expected sizes of 1, 2, 4, 8. Other size
+ * values will not trigger access.
+ */
+ if ((off & (size - 1)) != 0)
+ return (-1);
+#endif
+
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ if (((start = adapter->unm_nic_pci_set_window(adapter, off)) == -1UL) ||
+ (unm_nic_pci_is_same_window(adapter, off + size -1) == 0)) {
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ cmn_err(CE_WARN, "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", unm_nic_driver_name, off);
+ return (-1);
+ }
+
+ addr = (void *) (uptr_t)(pci_base_offset(adapter, start));
+ if (!addr)
+ addr = (void *) ((uint8_t *)adapter->ahw.pci_base0 + start);
+
+ switch (size) {
+ case 1:
+ UNM_NIC_PCI_WRITE_8(*(__uint8_t *)data, addr);
+ break;
+ case 2:
+ UNM_NIC_PCI_WRITE_16(*(__uint16_t *)data, addr);
+ break;
+ case 4:
+ UNM_NIC_PCI_WRITE_32(*(__uint32_t *)data, addr);
+ break;
+ case 8:
+ UNM_NIC_PCI_WRITE_64(*(__uint64_t *)data, addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ return (ret);
+}
+
+
+int
+unm_nic_pci_mem_write_128M(struct unm_adapter_s *adapter, u64 off, void *data,
+ int size)
+{
+ int i, j, ret = 0, loop, sz[2], off0;
+ __uint32_t temp;
+ __uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+#define MAX_CTL_CHECK 1000
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return (unm_nic_pci_mem_write_direct(adapter, off, data, size));
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->unm_nic_pci_mem_read(adapter,
+ off8 + (i << 3), &word[i], 8))
+ return (-1);
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((__uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((__uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((__uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((__uint64_t *)data);
+ break;
+ }
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ UNM_NIC_PCI_WRITE_32(0,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ UNM_NIC_PCI_WRITE_32(word[i] & 0xffffffff,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+ UNM_NIC_PCI_WRITE_32((word[i] >> 32) & 0xffffffff,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+ UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+ UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE |
+ MIU_TA_CTL_WRITE,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = UNM_NIC_PCI_READ_32((void *)
+ (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0) {
+ break;
+ }
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ cmn_err(CE_WARN, "%s: %s Fail to write thru agent\n",
+ __FUNCTION__, unm_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ return (ret);
+}
+
+int
+unm_nic_pci_mem_read_128M(struct unm_adapter_s *adapter, u64 off, void *data,
+ int size)
+{
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ __uint32_t temp;
+ __uint64_t off8, val, mem_crb, word[2] = {0, 0};
+#define MAX_CTL_CHECK 1000
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return (unm_nic_pci_mem_read_direct(adapter, off, data, size));
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ mem_crb = (uptr_t)(pci_base_offset(adapter, UNM_CRB_DDR_NET));
+
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ UNM_NIC_PCI_WRITE_32((__uint32_t)(off8 + (i << 3)),
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ UNM_NIC_PCI_WRITE_32(0,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_ENABLE,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+ UNM_NIC_PCI_WRITE_32(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+ (void *) (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = UNM_NIC_PCI_READ_32((void *)
+ (uptr_t)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0) {
+ break;
+ }
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ cmn_err(CE_WARN, "%s: %s Fail to read through agent\n",
+ __FUNCTION__, unm_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ word[i] = 0;
+ for (k = start; k <= end; k++) {
+ word[i] |= ((__uint64_t)UNM_NIC_PCI_READ_32(
+ (void *) (uptr_t)(mem_crb +
+ MIU_TEST_AGT_RDDATA(k))) << (32*k));
+ }
+ }
+
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+
+ if (j >= MAX_CTL_CHECK)
+ return (-1);
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(__uint8_t *)data = val;
+ break;
+ case 2:
+ *(__uint16_t *)data = val;
+ break;
+ case 4:
+ *(__uint32_t *)data = val;
+ break;
+ case 8:
+ *(__uint64_t *)data = val;
+ break;
+ }
+ return (0);
+}
+
+
+
+int
+unm_nic_pci_mem_write_2M(struct unm_adapter_s *adapter, u64 off, void *data,
+ int size)
+{
+ int i, j, ret = 0, loop, sz[2], off0;
+ __uint32_t temp;
+ __uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+#define MAX_CTL_CHECK 1000
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
+ mem_crb = UNM_CRB_QDR_NET;
+ } else {
+ mem_crb = UNM_CRB_DDR_NET;
+ if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return (unm_nic_pci_mem_write_direct(adapter,
+ off, data, size));
+ }
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->unm_nic_pci_mem_read(adapter,
+ off8 + (i << 3), &word[i], 8))
+ return (-1);
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((__uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((__uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((__uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((__uint64_t *)data);
+ break;
+ }
+
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+// don't lock here - write_wx gets the lock if each time
+// UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+// unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = word[i] & 0xffffffff;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+ temp = (word[i] >> 32) & 0xffffffff;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->unm_nic_hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0) {
+ break;
+ }
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ cmn_err(CE_WARN, "%s: Fail to write through agent\n",
+ unm_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+// unm_nic_pci_change_crbwindow_128M(adapter, 1);
+// UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ return (ret);
+}
+
+int
+unm_nic_pci_mem_read_2M(struct unm_adapter_s *adapter, u64 off, void *data,
+ int size)
+{
+// unsigned long flags;
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ __uint32_t temp;
+ __uint64_t off8, val, mem_crb, word[2] = {0, 0};
+#define MAX_CTL_CHECK 1000
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+
+ if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
+ mem_crb = UNM_CRB_QDR_NET;
+ } else {
+ mem_crb = UNM_CRB_DDR_NET;
+ if (unm_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return (unm_nic_pci_mem_read_direct(adapter,
+ off, data, size));
+ }
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+
+// don't get lock - write_wx will get it
+// UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+// unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ adapter->unm_nic_hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->unm_nic_hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0) {
+ break;
+ }
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ cmn_err(CE_WARN, "%s: Fail to read through agent\n",
+ unm_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ adapter->unm_nic_hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+ word[i] |= ((__uint64_t)temp << (32 * k));
+ }
+ }
+
+// unm_nic_pci_change_crbwindow_128M(adapter, 1);
+// UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+
+ if (j >= MAX_CTL_CHECK)
+ return (-1);
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(__uint8_t *)data = val;
+ break;
+ case 2:
+ *(__uint16_t *)data = val;
+ break;
+ case 4:
+ *(__uint32_t *)data = val;
+ break;
+ case 8:
+ *(__uint64_t *)data = val;
+ break;
+ }
+ return (0);
+}
+
+int
+unm_crb_writelit_adapter_2M(struct unm_adapter_s *adapter, unsigned long off,
+ int data)
+{
+ return (unm_nic_hw_write_wx_2M(adapter, off, &data, 4));
+}
+
+int
+unm_crb_writelit_adapter_128M(struct unm_adapter_s *adapter, unsigned long off,
+ int data)
+{
+ void *addr;
+
+ if (ADDR_IN_WINDOW1(off)) {
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ UNM_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off));
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ } else {
+ // unm_nic_write_w0 (adapter, off, data);
+ UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+ addr = (void *) (pci_base_offset(adapter, off));
+ UNM_NIC_PCI_WRITE_32(data, addr);
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
+ }
+
+ return (0);
+}
+
+int
+unm_nic_get_board_info(struct unm_adapter_s *adapter)
+{
+ int rv = 0;
+ unm_board_info_t *boardinfo;
+ int i;
+ int addr = BRDCFG_START;
+ uint32_t *ptr32;
+ uint32_t gpioval;
+
+ boardinfo = &adapter->ahw.boardcfg;
+ ptr32 = (uint32_t *)boardinfo;
+
+ for (i = 0; i < sizeof (unm_board_info_t) / sizeof (uint32_t); i++) {
+ if (rom_fast_read(adapter, addr, (int *)ptr32) == -1) {
+ return (-1);
+ }
+ DPRINTF(1, (CE_WARN, "ROM(%d): %x\n", i, *ptr32));
+ ptr32++;
+ addr += sizeof (uint32_t);
+ }
+
+ if (boardinfo->magic != UNM_BDINFO_MAGIC) {
+ DPRINTF(1, (CE_WARN, "%s: ERROR reading board config."
+ " Read %x, expected %x\n", unm_nic_driver_name,
+ boardinfo->magic, UNM_BDINFO_MAGIC));
+ rv = -1;
+ }
+
+ if (boardinfo->header_version != UNM_BDINFO_VERSION) {
+ DPRINTF(1, (CE_WARN, "%s: Unknown board config version."
+ " Read %x, expected %x\n", unm_nic_driver_name,
+ boardinfo->header_version, UNM_BDINFO_VERSION));
+ rv = -1;
+ }
+
+ if (boardinfo->board_type == UNM_BRDTYPE_P3_4_GB_MM) {
+ gpioval = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_PAD_GPIO_I,
+ adapter);
+ if ((gpioval & 0x8000) == 0)
+ boardinfo->board_type = UNM_BRDTYPE_P3_10G_TRP;
+ }
+
+ DPRINTF(0, (CE_WARN, "Discovered board type:0x%x ",
+ boardinfo->board_type));
+
+ switch ((unm_brdtype_t)boardinfo->board_type) {
+ case UNM_BRDTYPE_P2_SB35_4G:
+ adapter->ahw.board_type = UNM_NIC_GBE;
+ break;
+ case UNM_BRDTYPE_P2_SB31_10G:
+ case UNM_BRDTYPE_P2_SB31_10G_IMEZ:
+ case UNM_BRDTYPE_P2_SB31_10G_HMEZ:
+ case UNM_BRDTYPE_P2_SB31_10G_CX4:
+ case UNM_BRDTYPE_P3_HMEZ:
+ case UNM_BRDTYPE_P3_XG_LOM:
+ case UNM_BRDTYPE_P3_10G_CX4:
+ case UNM_BRDTYPE_P3_10G_CX4_LP:
+ case UNM_BRDTYPE_P3_IMEZ:
+ case UNM_BRDTYPE_P3_10G_SFP_PLUS:
+ case UNM_BRDTYPE_P3_10G_XFP:
+ case UNM_BRDTYPE_P3_10000_BASE_T:
+ adapter->ahw.board_type = UNM_NIC_XGBE;
+ break;
+ case UNM_BRDTYPE_P3_REF_QG:
+ case UNM_BRDTYPE_P3_4_GB:
+ case UNM_BRDTYPE_P3_4_GB_MM:
+ adapter->ahw.board_type = UNM_NIC_GBE;
+ break;
+ case UNM_BRDTYPE_P1_BD:
+ case UNM_BRDTYPE_P1_SB:
+ case UNM_BRDTYPE_P1_SMAX:
+ case UNM_BRDTYPE_P1_SOCK:
+ adapter->ahw.board_type = UNM_NIC_GBE;
+ break;
+ case UNM_BRDTYPE_P3_10G_TRP:
+ if (adapter->portnum < 2)
+ adapter->ahw.board_type = UNM_NIC_XGBE;
+ else
+ adapter->ahw.board_type = UNM_NIC_GBE;
+ break;
+ default:
+ DPRINTF(1, (CE_WARN, "%s: Unknown(%x)\n", unm_nic_driver_name,
+ boardinfo->board_type));
+ break;
+ }
+
+ return (rv);
+}
+
+/* NIU access sections */
+
+int
+unm_nic_macaddr_set(struct unm_adapter_s *adapter, __uint8_t *addr)
+{
+ int ret = 0, i, retry_count = 10;
+ unsigned char mac_addr[MAX_ADDR_LEN];
+
+ /* For P3, we should not set MAC in HW any more */
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return (0);
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ /*
+ * Flaky Mac address registers on qgig require several writes.
+ */
+ for (i = 0; i < retry_count; ++i) {
+ if (unm_niu_macaddr_set(adapter, addr) != 0)
+ return (-1);
+
+ (void) unm_niu_macaddr_get(adapter,
+ (unsigned char *)mac_addr);
+ if (memcmp(mac_addr, addr, 6) == 0)
+ return (0);
+ }
+ cmn_err(CE_WARN, "%s: Flaky MAC addr registers\n",
+ unm_nic_driver_name);
+ break;
+
+ case UNM_NIC_XGBE:
+ ret = unm_niu_xg_macaddr_set(adapter, addr);
+ break;
+
+ default:
+ cmn_err(CE_WARN, "\r\nUnknown board type encountered"
+ " while setting the MAC address.\n");
+ return (-1);
+ }
+ return (ret);
+}
+
+#define MTU_FUDGE_FACTOR 100
+int
+unm_nic_set_mtu(struct unm_adapter_s *adapter, int new_mtu)
+{
+ long port = adapter->physical_port;
+ int ret = 0;
+ u32 port_mode = 0;
+
+ if (adapter->ahw.revision_id >= NX_P3_A2)
+ return (nx_fw_cmd_set_mtu(adapter, new_mtu));
+
+ new_mtu += MTU_FUDGE_FACTOR; /* so that MAC accepts frames > MTU */
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ unm_nic_write_w0(adapter,
+ UNM_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
+ new_mtu);
+
+ break;
+
+ case UNM_NIC_XGBE:
+ adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
+ &port_mode, 4);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ unm_nic_write_w0(adapter,
+ UNM_NIU_AP_MAX_FRAME_SIZE(port), new_mtu);
+ } else {
+ if (adapter->physical_port == 0) {
+ unm_nic_write_w0(adapter,
+ UNM_NIU_XGE_MAX_FRAME_SIZE,
+ new_mtu);
+ } else {
+ unm_nic_write_w0(adapter,
+ UNM_NIU_XG1_MAX_FRAME_SIZE,
+ new_mtu);
+ }
+ }
+ break;
+
+ default:
+ cmn_err(CE_WARN, "%s: Unknown brdtype\n",
+ unm_nic_driver_name);
+ }
+
+ return (ret);
+}
+
+int
+unm_nic_set_promisc_mode(struct unm_adapter_s *adapter)
+{
+ int ret;
+
+ if (adapter->promisc)
+ return (0);
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ ret = unm_niu_set_promiscuous_mode(adapter,
+ UNM_NIU_PROMISCOUS_MODE);
+ break;
+
+ case UNM_NIC_XGBE:
+ ret = unm_niu_xg_set_promiscuous_mode(adapter,
+ UNM_NIU_PROMISCOUS_MODE);
+ break;
+
+ default:
+ cmn_err(CE_WARN, "%s: Unknown brdtype\n",
+ unm_nic_driver_name);
+ ret = -1;
+ break;
+ }
+
+if (!ret)
+ adapter->promisc = 1;
+
+ return (ret);
+}
+
+int
+unm_nic_unset_promisc_mode(struct unm_adapter_s *adapter)
+{
+ int ret = 0;
+
+ /*
+ * P3 does not unset promiscous mode. Why?
+ */
+ if (adapter->ahw.revision_id >= NX_P3_A2) {
+ return (0);
+ }
+
+ if (!adapter->promisc)
+ return (0);
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ ret = unm_niu_set_promiscuous_mode(adapter,
+ UNM_NIU_NON_PROMISCOUS_MODE);
+ break;
+
+ case UNM_NIC_XGBE:
+ ret = unm_niu_xg_set_promiscuous_mode(adapter,
+ UNM_NIU_NON_PROMISCOUS_MODE);
+ break;
+
+ default:
+ cmn_err(CE_WARN, "%s: Unknown brdtype\n",
+ unm_nic_driver_name);
+ ret = -1;
+ break;
+ }
+
+ if (!ret)
+ adapter->promisc = 0;
+
+ return (ret);
+}
+
+long
+unm_nic_phy_read(unm_adapter *adapter, long reg,
+ __uint32_t *readval)
+{
+ long ret = 0;
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ ret = unm_niu_gbe_phy_read(adapter, reg, readval);
+ break;
+
+ case UNM_NIC_XGBE:
+ DPRINTF(1, (CE_WARN,
+ "%s: Function %s is not implemented for XG\n",
+ unm_nic_driver_name, __FUNCTION__));
+ break;
+
+ default:
+ DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
+ unm_nic_driver_name));
+ }
+
+ return (ret);
+}
+
+long
+unm_nic_init_port(struct unm_adapter_s *adapter)
+{
+ long portnum = adapter->physical_port;
+ long ret = 0;
+ long reg = 0;
+ unm_niu_gbe_ifmode_t mode_dont_care = 0;
+ u32 port_mode = 0;
+
+ unm_nic_set_link_parameters(adapter);
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ ret = unm_niu_enable_gbe_port(adapter, mode_dont_care);
+ break;
+
+ case UNM_NIC_XGBE:
+ adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
+ &port_mode, 4);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ ret = unm_niu_enable_gbe_port(adapter, mode_dont_care);
+ } else {
+ adapter->unm_crb_writelit_adapter(adapter,
+ UNM_NIU_XGE_CONFIG_0 + (0x10000 * portnum), 0x5);
+ UNM_CRB_READ_CHECK_ADAPTER(UNM_NIU_XGE_CONFIG_1 +
+ (0x10000 * portnum), &reg, adapter);
+ if (adapter->ahw.revision_id < NX_P3_A2)
+ reg = (reg & ~0x2000UL);
+ adapter->unm_crb_writelit_adapter(adapter,
+ UNM_NIU_XGE_CONFIG_1 + (0x10000 * portnum), reg);
+ }
+ break;
+
+ default:
+ DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
+ unm_nic_driver_name));
+ }
+
+ return (ret);
+}
+
+void
+unm_nic_stop_port(struct unm_adapter_s *adapter)
+{
+
+ mac_unregister(adapter->mach);
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ (void) unm_niu_disable_gbe_port(adapter);
+ break;
+
+ case UNM_NIC_XGBE:
+ (void) unm_niu_disable_xg_port(adapter);
+ break;
+
+ default:
+ DPRINTF(1, (CE_WARN, "%s: Unknown board type\n",
+ unm_nic_driver_name));
+ }
+}
+
+void
+unm_crb_write_adapter(unsigned long off, void *data,
+ struct unm_adapter_s *adapter)
+{
+ (void) adapter->unm_nic_hw_write_wx(adapter, off, data, 4);
+}
+
+int
+unm_crb_read_adapter(unsigned long off, void *data,
+ struct unm_adapter_s *adapter)
+{
+ return (adapter->unm_nic_hw_read_wx(adapter, off, data, 4));
+}
+
+int
+unm_crb_read_val_adapter(unsigned long off, struct unm_adapter_s *adapter)
+{
+ int data;
+
+ adapter->unm_nic_hw_read_wx(adapter, off, &data, 4);
+ return (data);
+}
+
+void
+unm_nic_set_link_parameters(struct unm_adapter_s *adapter)
+{
+ unm_niu_phy_status_t status;
+ uint16_t defval = (uint16_t)-1;
+ unm_niu_control_t mode;
+ u32 port_mode = 0;
+
+ unm_nic_read_w0(adapter, UNM_NIU_MODE, (uint32_t *)&mode);
+ if (mode.enable_ge) { // Gb 10/100/1000 Mbps mode
+ adapter->unm_nic_hw_read_wx(adapter, UNM_PORT_MODE_ADDR,
+ &port_mode, 4);
+ if (port_mode == UNM_PORT_MODE_802_3_AP) {
+ adapter->link_speed = MBPS_1000;
+ adapter->link_duplex = LINK_DUPLEX_FULL;
+ } else {
+ if (unm_nic_phy_read(adapter,
+ UNM_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ (unm_crbword_t *)&status) == 0) {
+ if (status.link) {
+ switch (status.speed) {
+ case 0: adapter->link_speed = MBPS_10;
+ break;
+ case 1: adapter->link_speed = MBPS_100;
+ break;
+ case 2: adapter->link_speed = MBPS_1000;
+ break;
+ default:
+ adapter->link_speed = defval;
+ break;
+ }
+ switch (status.duplex) {
+ case 0: adapter->link_duplex = LINK_DUPLEX_HALF;
+ break;
+ case 1: adapter->link_duplex = LINK_DUPLEX_FULL;
+ break;
+ default:
+ adapter->link_duplex = defval;
+ break;
+ }
+ } else {
+ adapter->link_speed = defval;
+ adapter->link_duplex = defval;
+ }
+ } else {
+ adapter->link_speed = defval;
+ adapter->link_duplex = defval;
+ }
+ }
+ }
+}
+
+void
+unm_nic_flash_print(struct unm_adapter_s *adapter)
+{
+ int valid = 1;
+ unm_board_info_t *board_info = &(adapter->ahw.boardcfg);
+
+ if (board_info->magic != UNM_BDINFO_MAGIC) {
+ cmn_err(CE_WARN, "%s UNM Unknown board config, Read 0x%x "
+ "expected as 0x%x\n", unm_nic_driver_name,
+ board_info->magic, UNM_BDINFO_MAGIC);
+ valid = 0;
+ }
+ if (board_info->header_version != UNM_BDINFO_VERSION) {
+ cmn_err(CE_WARN, "%s UNM Unknown board config version."
+ " Read %x, expected %x\n", unm_nic_driver_name,
+ board_info->header_version, UNM_BDINFO_VERSION);
+ valid = 0;
+ }
+ if (valid) {
+ unm_user_info_t user_info;
+ int i;
+ int addr = USER_START;
+ int *ptr32;
+
+ ptr32 = (int *)&user_info;
+ for (i = 0; i < sizeof (unm_user_info_t) / sizeof (uint32_t);
+ i++) {
+ if (rom_fast_read(adapter, addr, ptr32) == -1) {
+ cmn_err(CE_WARN,
+ "%s: ERROR reading %s board userarea.\n",
+ unm_nic_driver_name, unm_nic_driver_name);
+ return;
+ }
+ ptr32++;
+ addr += sizeof (uint32_t);
+ }
+ if (verbmsg != 0) {
+ char *brd_name;
+ GET_BRD_NAME_BY_TYPE(board_info->board_type, brd_name);
+ cmn_err(CE_NOTE, "%s %s Board S/N %s Chip id 0x%x\n",
+ unm_nic_driver_name, brd_name, user_info.serial_num,
+ board_info->chip_id);
+ }
+ }
+}
+
+static int
+nx_nic_send_cmd_descs(unm_adapter *adapter, cmdDescType0_t *cmd_desc_arr,
+ int nr_elements)
+{
+ struct unm_cmd_buffer *pbuf;
+ unsigned int i = 0, producer;
+
+ /*
+ * We need to check if space is available.
+ */
+ UNM_SPIN_LOCK(&adapter->tx_lock);
+ producer = adapter->cmdProducer;
+
+ do {
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->head = pbuf->tail = NULL;
+ pbuf->msg = NULL;
+ (void) memcpy(&adapter->ahw.cmdDescHead[producer],
+ &cmd_desc_arr[i], sizeof (cmdDescType0_t));
+ unm_desc_dma_sync(adapter->ahw.cmd_desc_dma_handle, producer,
+ 1, adapter->MaxTxDescCount, sizeof (cmdDescType0_t),
+ DDI_DMA_SYNC_FORDEV);
+ producer = get_next_index(producer, adapter->MaxTxDescCount);
+ i++;
+ } while (i != nr_elements);
+
+ adapter->cmdProducer = adapter->ahw.cmdProducer = producer;
+ adapter->freecmds -= i;
+
+ unm_nic_update_cmd_producer(adapter, producer);
+
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+ return (0);
+}
+
+typedef struct {
+ u64 qhdr, req_hdr, words[6];
+} nx_nic_req_t;
+
+typedef struct {
+ u8 op, tag, mac_addr[6];
+} nx_mac_req_t;
+
+static void
+nx_p3_sre_macaddr_change(unm_adapter *adapter, u8 *addr, u8 op)
+{
+ nx_nic_req_t req;
+ nx_mac_req_t mac_req;
+ int rv;
+
+ (void) memset(&req, 0, sizeof (nx_nic_req_t));
+ req.qhdr |= (NX_NIC_REQUEST << 23);
+ req.req_hdr |= NX_MAC_EVENT;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+ mac_req.op = op;
+ (void) memcpy(&mac_req.mac_addr, addr, 6);
+ req.words[0] = HOST_TO_LE_64(*(u64 *)(uintptr_t)&mac_req);
+
+ rv = nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1);
+ if (rv != 0)
+ cmn_err(CE_WARN, "%s%d: Could not send mac update\n",
+ adapter->name, adapter->instance);
+}
+
+static int
+nx_p3_nic_set_promisc(unm_adapter *adapter, u32 mode)
+{
+ nx_nic_req_t req;
+
+ (void) memset(&req, 0, sizeof (nx_nic_req_t));
+
+ req.qhdr |= (NX_HOST_REQUEST << 23);
+ req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+ req.words[0] = HOST_TO_LE_64(mode);
+
+ return (nx_nic_send_cmd_descs(adapter, (cmdDescType0_t *)&req, 1));
+}
+
+/*
+ * Currently only invoked at interface initialization time
+ */
+void
+nx_p3_nic_set_multi(unm_adapter *adapter)
+{
+ u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ if (nx_p3_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL))
+ cmn_err(CE_WARN, "Could not set promisc mode\n");
+
+ nx_p3_sre_macaddr_change(adapter, adapter->mac_addr, NETXEN_MAC_ADD);
+ nx_p3_sre_macaddr_change(adapter, bcast_addr, NETXEN_MAC_ADD);
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_hw.h b/usr/src/uts/common/io/ntxn/unm_nic_hw.h
new file mode 100644
index 0000000000..a7e4739096
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_hw.h
@@ -0,0 +1,107 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _UNM_NIC_HW_
+#define _UNM_NIC_HW_
+
+#include "unm_inc.h"
+
+/* Hardware memory size of 128 meg */
+#define BAR0_SIZE (128 * 1024 * 1024)
+/*
+ * It can be calculated by looking at the first 1 bit of the BAR0 addr after
+ * bit 4 For us lets assume that BAR0 is D8000008, then the size is 0x8000000,
+ * 8 represents first bit containing 1. FSL temp notes....pg 162 of PCI
+ * systems arch...
+ */
+
+#define UNM_NIC_HW_BLOCK_WRITE_64(DATA_PTR, ADDR, NUM_WORDS) \
+{ \
+ int i; \
+ u64 *a = (u64 *) (DATA_PTR); \
+ u64 *b = (u64 *) (ADDR); \
+ u64 tmp; \
+ for (i = 0; i < (NUM_WORDS); i++, a++, b++) { \
+ tmp = UNM_NIC_PCI_READ_64(a); \
+ UNM_NIC_PCI_WRITE_64(tmp, b); \
+ } \
+}
+
+#define UNM_NIC_HW_BLOCK_READ_64(DATA_PTR, ADDR, NUM_WORDS) \
+{ \
+ int i; \
+ u64 *a = (u64 *) (DATA_PTR); \
+ u64 *b = (u64 *) (ADDR); \
+ u64 tmp; \
+ for (i = 0; i < (NUM_WORDS); i++, a++, b++) { \
+ tmp = UNM_NIC_PCI_READ_64(b); \
+ UNM_NIC_PCI_WRITE_64(tmp, a); \
+ } \
+}
+
+#define UNM_PCI_MAPSIZE_BYTES (UNM_PCI_MAPSIZE << 20)
+
+#define UNM_NIC_LOCKED_READ_REG(X, Y) \
+ addr = (void *)(pci_base_offset(adapter, (X))); \
+ *(uint32_t *)(Y) = UNM_NIC_PCI_READ_32(addr);
+
+#define UNM_NIC_LOCKED_WRITE_REG(X, Y) \
+ addr = (void *)(pci_base_offset(adapter, (X))); \
+ UNM_NIC_PCI_WRITE_32(*(uint32_t *)(Y), addr);
+
+/* For Multicard support */
+#define UNM_CRB_READ_VAL_ADAPTER(ADDR, ADAPTER) \
+ unm_crb_read_val_adapter((ADDR), (struct unm_adapter_s *)ADAPTER)
+
+#define UNM_CRB_READ_CHECK_ADAPTER(ADDR, VALUE, ADAPTER) \
+ { \
+ if (unm_crb_read_adapter(ADDR, VALUE, \
+ (struct unm_adapter_s *)ADAPTER)) return -1; \
+ }
+
+#define UNM_CRB_WRITELIT_ADAPTER(ADDR, VALUE, ADAPTER) \
+ { \
+ adapter->unm_crb_writelit_adapter( \
+ (struct unm_adapter_s *)ADAPTER, \
+ (unsigned long)ADDR, (int)VALUE); \
+ }
+
+struct unm_adapter_s;
+void unm_nic_set_link_parameters(struct unm_adapter_s *adapter);
+long xge_mdio_init(struct unm_adapter_s *adapter);
+void unm_nic_flash_print(struct unm_adapter_s *adapter);
+void unm_nic_get_serial_num(struct unm_adapter_s *adapter);
+
+typedef struct {
+ unsigned valid;
+ unsigned start_128M;
+ unsigned end_128M;
+ unsigned start_2M;
+} crb_128M_2M_sub_block_map_t;
+
+typedef struct {
+ crb_128M_2M_sub_block_map_t sub_block[16];
+} crb_128M_2M_block_map_t;
+
+#endif /* _UNM_NIC_HW_ */
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_init.c b/usr/src/uts/common/io/ntxn/unm_nic_init.c
new file mode 100644
index 0000000000..89e78c10de
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_init.c
@@ -0,0 +1,512 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+#include <sys/pci.h>
+
+#include "unm_nic.h"
+#include "unm_nic_hw.h"
+#include "nic_cmn.h"
+#include "unm_nic_ioctl.h"
+#include "nic_phan_reg.h"
+
+struct crb_addr_pair {
+ long addr, data;
+};
+
+#define MAX_CRB_XFORM 60
+#define ADDR_ERROR ((unsigned long)0xffffffff)
+
+#define crb_addr_transform(name) \
+ crb_addr_xform[UNM_HW_PX_MAP_CRB_##name] = \
+ UNM_HW_CRB_HUB_AGT_ADR_##name << 20
+
+static unsigned int crb_addr_xform[MAX_CRB_XFORM];
+
+static void
+crb_addr_transform_setup(void)
+{
+ crb_addr_transform(XDMA);
+ crb_addr_transform(TIMR);
+ crb_addr_transform(SRE);
+ crb_addr_transform(SQN3);
+ crb_addr_transform(SQN2);
+ crb_addr_transform(SQN1);
+ crb_addr_transform(SQN0);
+ crb_addr_transform(SQS3);
+ crb_addr_transform(SQS2);
+ crb_addr_transform(SQS1);
+ crb_addr_transform(SQS0);
+ crb_addr_transform(RPMX7);
+ crb_addr_transform(RPMX6);
+ crb_addr_transform(RPMX5);
+ crb_addr_transform(RPMX4);
+ crb_addr_transform(RPMX3);
+ crb_addr_transform(RPMX2);
+ crb_addr_transform(RPMX1);
+ crb_addr_transform(RPMX0);
+ crb_addr_transform(ROMUSB);
+ crb_addr_transform(SN);
+ crb_addr_transform(QMN);
+ crb_addr_transform(QMS);
+ crb_addr_transform(PGNI);
+ crb_addr_transform(PGND);
+ crb_addr_transform(PGN3);
+ crb_addr_transform(PGN2);
+ crb_addr_transform(PGN1);
+ crb_addr_transform(PGN0);
+ crb_addr_transform(PGSI);
+ crb_addr_transform(PGSD);
+ crb_addr_transform(PGS3);
+ crb_addr_transform(PGS2);
+ crb_addr_transform(PGS1);
+ crb_addr_transform(PGS0);
+ crb_addr_transform(PS);
+ crb_addr_transform(PH);
+ crb_addr_transform(NIU);
+ crb_addr_transform(I2Q);
+ crb_addr_transform(EG);
+ crb_addr_transform(MN);
+ crb_addr_transform(MS);
+ crb_addr_transform(CAS2);
+ crb_addr_transform(CAS1);
+ crb_addr_transform(CAS0);
+ crb_addr_transform(CAM);
+ crb_addr_transform(C2C1);
+ crb_addr_transform(C2C0);
+ crb_addr_transform(SMB);
+ crb_addr_transform(OCM0);
+
+ /*
+ * Used only in P3 just define it for P2 also.
+ */
+ crb_addr_transform(I2C0);
+}
+
+/*
+ * decode_crb_addr(0 - utility to translate from internal Phantom CRB address
+ * to external PCI CRB address.
+ */
+static unsigned long
+decode_crb_addr(unsigned long addr)
+{
+ int i;
+ unsigned long base_addr, offset, pci_base;
+
+ crb_addr_transform_setup();
+
+ pci_base = ADDR_ERROR;
+ base_addr = addr & 0xfff00000;
+ offset = addr & 0x000fffff;
+
+ for (i = 0; i < MAX_CRB_XFORM; i++) {
+ if (crb_addr_xform[i] == base_addr) {
+ pci_base = i << 20;
+ break;
+ }
+ }
+
+ if (pci_base == ADDR_ERROR) {
+ return (pci_base);
+ } else {
+ return (pci_base + offset);
+ }
+}
+
+static long rom_max_timeout = 100;
+static long rom_lock_timeout = 10000;
+
+static int
+rom_lock(unm_adapter *adapter)
+{
+ uint32_t done = 0;
+ long timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore2 from PCI HW block */
+ unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
+ if (done == 1)
+ break;
+ if (timeout >= rom_lock_timeout) {
+ cmn_err(CE_WARN, "%s%d rom_lock timed out %d %ld\n",
+ adapter->name, adapter->instance, done, timeout);
+ return (-1);
+ }
+ timeout++;
+ }
+ unm_nic_reg_write(adapter, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+ return (0);
+}
+
+static void
+rom_unlock(unm_adapter *adapter)
+{
+ uint32_t val;
+
+ /* release semaphore2 */
+ unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
+}
+
+static int
+wait_rom_done(unm_adapter *adapter)
+{
+ long timeout = 0;
+ long done = 0;
+
+ while (done == 0) {
+ unm_nic_reg_read(adapter, UNM_ROMUSB_GLB_STATUS, &done);
+ done &= 2;
+ timeout++;
+ if (timeout >= rom_max_timeout) {
+ cmn_err(CE_WARN,
+ "Timeout reached waiting for rom done");
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+do_rom_fast_read(unm_adapter *adapter, int addr, int *valp)
+{
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ADDRESS, addr);
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
+ drv_usecwait(100); /* prevent bursting on CRB */
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+ if (wait_rom_done(adapter) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Error waiting for rom done\n");
+ return (-1);
+ }
+
+ // reset abyte_cnt and dummy_byte_cnt
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
+ drv_usecwait(100); /* prevent bursting on CRB */
+ unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+
+ unm_nic_reg_read(adapter, UNM_ROMUSB_ROM_RDATA, valp);
+ return (0);
+}
+
+int
+rom_fast_read(struct unm_adapter_s *adapter, int addr, int *valp)
+{
+ int ret;
+
+ if (rom_lock(adapter) != 0) {
+ cmn_err(CE_WARN, "%s(%d)rom_lock failed\n",
+ __FUNCTION__, __LINE__);
+ return (-1);
+ }
+
+ ret = do_rom_fast_read(adapter, addr, valp);
+ if (ret != 0) {
+ cmn_err(CE_WARN, "%s do_rom_fast_read returned: %d\n",
+ __FUNCTION__, __LINE__);
+ return (-1);
+ }
+ rom_unlock(adapter);
+ return (ret);
+}
+
+int
+pinit_from_rom(struct unm_adapter_s *adapter, int verbose)
+{
+ int addr, val, status, i, init_delay = 0, n;
+ struct crb_addr_pair *buf;
+ unsigned long off;
+ unsigned int offset;
+
+ status = unm_nic_get_board_info(adapter);
+ if (status)
+ cmn_err(CE_WARN, "%s: pinit_from_rom: Error getting brdinfo\n",
+ unm_nic_driver_name);
+
+ UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET, 0xffffffff, adapter);
+
+ if (verbose) {
+ int val;
+ if (rom_fast_read(adapter, 0x4008, &val) == 0)
+ cmn_err(CE_WARN, "P2 ROM board type: 0x%08x\n", val);
+ else
+ cmn_err(CE_WARN, "Could not read board type\n");
+ if (rom_fast_read(adapter, 0x400c, &val) == 0)
+ cmn_err(CE_WARN, "ROM board num: 0x%08x\n", val);
+ else
+ cmn_err(CE_WARN, "Could not read board number\n");
+ if (rom_fast_read(adapter, 0x4010, &val) == 0)
+ cmn_err(CE_WARN, "ROM chip num: 0x%08x\n", val);
+ else
+ cmn_err(CE_WARN, "Could not read chip number\n");
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (rom_fast_read(adapter, 0, &n) != 0 ||
+ (unsigned int)n != 0xcafecafe ||
+ rom_fast_read(adapter, 4, &n) != 0) {
+ cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", unm_nic_driver_name, n);
+ return (-1);
+ }
+
+ offset = n & 0xffffU;
+ n = (n >> 16) & 0xffffU;
+ } else {
+ if (rom_fast_read(adapter, 0, &n) != 0 ||
+ !(n & 0x80000000)) {
+ cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", unm_nic_driver_name, n);
+ return (-1);
+ }
+ offset = 1;
+ n &= ~0x80000000;
+ }
+
+ if (n >= 1024) {
+ cmn_err(CE_WARN, "%s: %s:n=0x%x Card flash not initialized\n",
+ unm_nic_driver_name, __FUNCTION__, n);
+ return (-1);
+ }
+
+ if (verbose)
+ cmn_err(CE_WARN, "%s: %d CRB init values found in ROM.\n",
+ unm_nic_driver_name, n);
+
+ buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
+ if (buf == NULL) {
+ cmn_err(CE_WARN, "%s: pinit_from_rom: Unable to get memory\n",
+ unm_nic_driver_name);
+ return (-1);
+ }
+
+ for (i = 0; i < n; i++) {
+ if (rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+ rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
+ kmem_free(buf, n * sizeof (struct crb_addr_pair));
+ return (-1);
+ }
+
+ buf[i].addr = addr;
+ buf[i].data = val;
+
+ if (verbose)
+ cmn_err(CE_WARN, "%s: PCI: 0x%08x == 0x%08x\n",
+ unm_nic_driver_name,
+ (unsigned int)decode_crb_addr(
+ (unsigned long)addr), val);
+ }
+
+ for (i = 0; i < n; i++) {
+ off = decode_crb_addr((unsigned long)buf[i].addr) +
+ UNM_PCI_CRBSPACE;
+ /* skipping cold reboot MAGIC */
+ if (off == UNM_CAM_RAM(0x1fc)) {
+ continue;
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ /* do not reset PCI */
+ if (off == (ROMUSB_GLB + 0xbc)) {
+ continue;
+ }
+ if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
+ continue;
+ if (off == (UNM_CRB_PEG_NET_1 + 0x18)) {
+ buf[i].data = 0x1020;
+ }
+ /* skip the function enable register */
+ if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
+ continue;
+ }
+ if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
+ continue;
+ }
+
+ if ((off & 0x0ff00000) == UNM_CRB_SMB) {
+ continue;
+ }
+
+ }
+
+ if (off == ADDR_ERROR) {
+ cmn_err(CE_WARN, "%s: Err: Unknown addr: 0x%08lx\n",
+ unm_nic_driver_name, buf[i].addr);
+ continue;
+ }
+
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == UNM_ROMUSB_GLB_SW_RESET) {
+ init_delay = 1;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ /* hold xdma in reset also */
+ buf[i].data = 0x8000ff;
+ }
+ }
+
+ adapter->unm_nic_hw_write_wx(adapter, off, &buf[i].data, 4);
+
+ if (init_delay == 1) {
+ nx_msleep(1000); /* Sleep 1000 msecs */
+ init_delay = 0;
+ }
+
+ nx_msleep(1); /* Sleep 1 msec */
+ }
+
+ kmem_free(buf, n * sizeof (struct crb_addr_pair));
+
+ // disable_peg_cache_all
+ // unreset_net_cache
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ val = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
+ adapter);
+ UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
+ (val & 0xffffff0f), adapter);
+ }
+
+ // p2dn replyCount
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0xec, 0x1e, adapter);
+ // disable_peg_cache 0
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0x4c, 8, adapter);
+ // disable_peg_cache 1
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_I+0x4c, 8, adapter);
+
+ // peg_clr_all
+ // peg_clr 0
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0x8, 0, adapter);
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0xc, 0, adapter);
+ // peg_clr 1
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0x8, 0, adapter);
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0xc, 0, adapter);
+ // peg_clr 2
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0x8, 0, adapter);
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0xc, 0, adapter);
+ // peg_clr 3
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0x8, 0, adapter);
+ UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0xc, 0, adapter);
+
+ return (0);
+}
+
+int
+phantom_init(struct unm_adapter_s *adapter, int pegtune_val)
+{
+ u32 val = 0;
+ int retries = 120;
+
+ if (!pegtune_val) {
+ do {
+ val = adapter->unm_nic_pci_read_normalize(adapter,
+ CRB_CMDPEG_STATE);
+
+ if ((val == PHAN_INITIALIZE_COMPLETE) ||
+ (val == PHAN_INITIALIZE_ACK))
+ return (DDI_SUCCESS);
+
+ /* 500 msec wait */
+ drv_usecwait(500000);
+ } while (--retries > 0);
+
+ if (!retries) {
+ val = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_ROMUSB_GLB_PEGTUNE_DONE);
+ cmn_err(CE_WARN, "WARNING: Initial boot wait loop"
+ "failed...state:%d\n", val);
+ return (DDI_FAILURE);
+ }
+ }
+
+ return (DDI_SUCCESS);
+}
+
+int
+load_from_flash(struct unm_adapter_s *adapter)
+{
+ int i;
+ long data, size = 0;
+ long flashaddr = BOOTLD_START, memaddr = BOOTLD_START;
+
+ size = (IMAGE_START - BOOTLD_START)/4;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ data = 1;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
+ &data, 4);
+ }
+
+ for (i = 0; i < size; i++) {
+ if (rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
+ cmn_err(CE_WARN, "Error in rom_fast_read: "
+ "Will skip loading flash image\n");
+ return (DDI_FAILURE);
+ }
+
+ adapter->unm_nic_pci_mem_write(adapter, memaddr, &data, 4);
+ flashaddr += 4;
+ memaddr += 4;
+ }
+
+ drv_usecwait(100);
+ UNM_READ_LOCK(&adapter->adapter_lock);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ data = 0x80001d;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
+ &data, 4);
+ } else {
+ data = 0x3fff;
+ adapter->unm_nic_hw_write_wx(adapter,
+ UNM_ROMUSB_GLB_CHIP_CLK_CTRL, &data, 4);
+ data = 0;
+ adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
+ &data, 4);
+ }
+
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ return (DDI_SUCCESS);
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_ioctl.h b/usr/src/uts/common/io/ntxn/unm_nic_ioctl.h
new file mode 100644
index 0000000000..1db4e49624
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_ioctl.h
@@ -0,0 +1,79 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef __UNM_NIC_IOCTL_H__
+#define __UNM_NIC_IOCTL_H__
+
+/* ioctl's dealing with PCI read/writes */
+#define UNM_CMD_START 0
+#define UNM_NIC_CMD (UNM_CMD_START + 1)
+#define UNM_NIC_NAME (UNM_CMD_START + 2)
+
+typedef enum {
+ unm_nic_cmd_none = 0,
+ unm_nic_cmd_pci_read,
+ unm_nic_cmd_pci_write,
+ unm_nic_cmd_pci_mem_read,
+ unm_nic_cmd_pci_mem_write,
+ unm_nic_cmd_pci_config_read,
+ unm_nic_cmd_pci_config_write,
+ unm_nic_cmd_get_stats,
+ unm_nic_cmd_clear_stats,
+ unm_nic_cmd_get_version,
+ unm_nic_cmd_get_phy_type,
+ unm_nic_cmd_efuse_chip_id,
+
+ unm_nic_cmd_flash_read = 50,
+ unm_nic_cmd_flash_write,
+ unm_nic_cmd_flash_se
+} unm_nic_ioctl_cmd_t;
+
+#pragma pack(1)
+
+typedef struct {
+ __uint32_t cmd;
+ __uint32_t unused1;
+ __uint64_t off;
+ __uint32_t size;
+ __uint32_t rv;
+ char uabc[64];
+ void *ptr;
+} unm_nic_ioctl_data_t;
+
+struct unm_statistics {
+ __uint64_t rx_packets;
+ __uint64_t tx_packets;
+ __uint64_t rx_bytes;
+ __uint64_t rx_errors;
+ __uint64_t tx_bytes;
+ __uint64_t tx_errors;
+ __uint64_t rx_CRC_errors;
+ __uint64_t rx_short_length_error;
+ __uint64_t rx_long_length_error;
+ __uint64_t rx_MAC_errors;
+};
+
+#pragma pack()
+
+#endif /* !__UNM_NIC_IOCTL_H__ */
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_isr.c b/usr/src/uts/common/io/ntxn/unm_nic_isr.c
new file mode 100644
index 0000000000..5ca220b473
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_isr.c
@@ -0,0 +1,127 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+
+#include <sys/pci.h>
+
+#include "unm_nic.h"
+#include "unm_nic_hw.h"
+#include "nic_cmn.h"
+#include "nic_phan_reg.h"
+
+static void
+unm_nic_isr_other(struct unm_adapter_s *adapter)
+{
+ u32 portno = adapter->portnum;
+ u32 val, linkup, qg_linksup = adapter->ahw.linkup;
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_read_wx(adapter, CRB_XG_STATE, &val, 4);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ linkup = 1 & (val >> adapter->physical_port);
+ adapter->ahw.linkup = linkup;
+
+ if (linkup != qg_linksup) {
+ cmn_err(CE_WARN, "%s: PORT %d link %s\n", unm_nic_driver_name,
+ portno, ((linkup == 0) ? "down" : "up"));
+ mac_link_update(adapter->mach, linkup);
+ if (linkup)
+ unm_nic_set_link_parameters(adapter);
+ }
+}
+
+void
+unm_nic_handle_phy_intr(struct unm_adapter_s *adapter)
+{
+ uint32_t val, val1, linkupval;
+
+ switch (adapter->ahw.board_type) {
+ case UNM_NIC_GBE:
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ unm_nic_isr_other(adapter);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case UNM_NIC_XGBE:
+ /* WINDOW = 1 */
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ adapter->unm_nic_hw_read_wx(adapter, CRB_XG_STATE_P3,
+ &val, 4);
+ val1 = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+ linkupval = XG_LINK_UP_P3;
+ } else {
+ adapter->unm_nic_hw_read_wx(adapter, CRB_XG_STATE,
+ &val, 4);
+ val >>= (adapter->portnum * 8);
+ val1 = val & 0xff;
+ linkupval = XG_LINK_UP;
+ }
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ if (adapter->ahw.linkup && (val1 != linkupval)) {
+ if (verbmsg != 0)
+ cmn_err(CE_NOTE, "%s%d: NIC Link is down\n",
+ adapter->name, adapter->portnum);
+ mac_link_update(adapter->mach, LINK_STATE_DOWN);
+ adapter->ahw.linkup = 0;
+ } else if ((adapter->ahw.linkup == 0) && (val1 == linkupval)) {
+ if (verbmsg != 0)
+ cmn_err(CE_NOTE, "%s%d: NIC Link is up\n",
+ adapter->name, adapter->portnum);
+ mac_link_update(adapter->mach, LINK_STATE_UP);
+ adapter->ahw.linkup = 1;
+
+ if (adapter->ahw.board_type == UNM_NIC_GBE)
+ unm_nic_set_link_parameters(adapter);
+ }
+
+ break;
+
+ default:
+ DPRINTF(0, (CE_WARN, "%s%d ISR: Unknown board type\n",
+ unm_nic_driver_name, adapter->portnum));
+ }
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_nic_main.c b/usr/src/uts/common/io/ntxn/unm_nic_main.c
new file mode 100644
index 0000000000..b7e0c5832d
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_nic_main.c
@@ -0,0 +1,2599 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#include <sys/kmem.h>
+#include <sys/stat.h>
+#include <sys/kstat.h>
+#include <sys/vtrace.h>
+#include <sys/dlpi.h>
+#include <sys/strsun.h>
+#include <sys/ethernet.h>
+#include <sys/modctl.h>
+#include <sys/errno.h>
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
+#include <sys/pci.h>
+
+#include <sys/gld.h>
+#include <netinet/in.h>
+#include <inet/ip.h>
+#include <inet/tcp.h>
+
+#include <sys/rwlock.h>
+#include <sys/mutex.h>
+#include <sys/pattr.h>
+#include <sys/strsubr.h>
+#include <sys/ddi_impldefs.h>
+#include<sys/task.h>
+
+#include "unm_nic_hw.h"
+#include "unm_nic.h"
+
+#include "nic_phan_reg.h"
+#include "unm_nic_ioctl.h"
+#include "nic_cmn.h"
+#include "unm_version.h"
+#include "unm_brdcfg.h"
+
+#if defined(lint)
+#undef MBLKL
+#define MBLKL(_mp_) ((uintptr_t)(_mp_)->b_wptr - (uintptr_t)(_mp_)->b_rptr)
+#endif /* lint */
+
+#undef UNM_LOOPBACK
+#undef SINGLE_DMA_BUF
+
+#define UNM_ADAPTER_UP_MAGIC 777
+#define VLAN_TAGSZ 0x4
+
+#define index2rxbuf(_rdp_, _idx_) ((_rdp_)->rx_buf_pool + (_idx_))
+#define rxbuf2index(_rdp_, _bufp_) ((_bufp_) - (_rdp_)->rx_buf_pool)
+
+/*
+ * Receive ISR processes NX_RX_MAXBUFS incoming packets at most, then posts
+ * as many buffers as packets processed. This loop repeats as required to
+ * process all incoming packets delivered in a single interrupt. Higher
+ * value of NX_RX_MAXBUFS improves performance by posting rx buffers less
+ * frequently, but at the cost of not posting quickly enough when card is
+ * running out of rx buffers.
+ */
+#define NX_RX_THRESHOLD 32
+#define NX_RX_MAXBUFS 128
+#define NX_MAX_TXCOMPS 256
+
+extern void unm_free_tx_buffers(unm_adapter *adapter);
+extern void unm_free_tx_dmahdl(unm_adapter *adapter);
+extern void unm_destroy_rx_ring(unm_rcv_desc_ctx_t *rcv_desc);
+
+static void unm_post_rx_buffers_nodb(struct unm_adapter_s *adapter,
+ uint32_t ringid);
+static mblk_t *unm_process_rcv(unm_adapter *adapter, statusDesc_t *desc);
+static int unm_process_rcv_ring(unm_adapter *, int);
+static int unm_process_cmd_ring(struct unm_adapter_s *adapter);
+
+static int unm_nic_do_ioctl(unm_adapter *adapter, queue_t *q, mblk_t *mp);
+static void unm_nic_ioctl(struct unm_adapter_s *adapter, int cmd, queue_t *q,
+ mblk_t *mp);
+
+/* GLDv3 interface functions */
+static int ntxn_m_start(void *);
+static void ntxn_m_stop(void *);
+static int ntxn_m_multicst(void *, boolean_t, const uint8_t *);
+static int ntxn_m_promisc(void *, boolean_t);
+static int ntxn_m_stat(void *arg, uint_t stat, uint64_t *val);
+static mblk_t *ntxn_m_tx(void *, mblk_t *);
+static void ntxn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
+static boolean_t ntxn_m_getcapab(void *arg, mac_capab_t cap, void *cap_data);
+
+/*
+ * Allocates DMA handle, virtual memory and binds them
+ * returns size of actual memory binded and the physical address.
+ */
+int
+unm_pci_alloc_consistent(unm_adapter *adapter,
+ int size, caddr_t *address, ddi_dma_cookie_t *cookie,
+ ddi_dma_handle_t *dma_handle, ddi_acc_handle_t *handlep)
+{
+ int err;
+ uint32_t ncookies;
+ size_t ring_len;
+ uint_t dma_flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
+
+ *dma_handle = NULL;
+
+ if (size <= 0)
+ return (DDI_ENOMEM);
+
+ err = ddi_dma_alloc_handle(adapter->dip,
+ &adapter->gc_dma_attr_desc,
+ DDI_DMA_DONTWAIT, NULL, dma_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "!%s: %s: ddi_dma_alloc_handle FAILED:"
+ " %d", unm_nic_driver_name, __func__, err);
+ return (DDI_ENOMEM);
+ }
+
+ err = ddi_dma_mem_alloc(*dma_handle,
+ size, &adapter->gc_attr_desc,
+ dma_flags & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
+ DDI_DMA_DONTWAIT, NULL, address, &ring_len,
+ handlep);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "!%s: %s: ddi_dma_mem_alloc failed:"
+ "ret %d, request size: %d",
+ unm_nic_driver_name, __func__, err, size);
+ ddi_dma_free_handle(dma_handle);
+ return (DDI_ENOMEM);
+ }
+
+ if (ring_len < size) {
+ cmn_err(CE_WARN, "%s: %s: could not allocate required "
+ "memory :%d\n", unm_nic_driver_name,
+ __func__, err);
+ ddi_dma_mem_free(handlep);
+ ddi_dma_free_handle(dma_handle);
+ return (DDI_FAILURE);
+ }
+
+ (void) memset(*address, 0, size);
+
+ if (((err = ddi_dma_addr_bind_handle(*dma_handle,
+ NULL, *address, ring_len,
+ dma_flags,
+ DDI_DMA_DONTWAIT, NULL,
+ cookie, &ncookies)) != DDI_DMA_MAPPED) ||
+ (ncookies != 1)) {
+ cmn_err(CE_WARN,
+ "!%s: %s: ddi_dma_addr_bind_handle FAILED: %d",
+ unm_nic_driver_name, __func__, err);
+ ddi_dma_mem_free(handlep);
+ ddi_dma_free_handle(dma_handle);
+ return (DDI_FAILURE);
+ }
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * Unbinds the memory, frees the DMA handle and at the end, frees the memory
+ */
+void
+unm_pci_free_consistent(ddi_dma_handle_t *dma_handle,
+ ddi_acc_handle_t *acc_handle)
+{
+ int err;
+
+ err = ddi_dma_unbind_handle(*dma_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s: Error unbinding memory\n", __func__);
+ return;
+ }
+
+ ddi_dma_mem_free(acc_handle);
+ ddi_dma_free_handle(dma_handle);
+}
+
+static uint32_t msi_tgt_status[] = {
+ ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
+};
+
+static void
+unm_nic_disable_int(unm_adapter *adapter)
+{
+ __uint32_t temp = 0;
+
+ adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
+ &temp, 4);
+}
+
+static inline int
+unm_nic_clear_int(unm_adapter *adapter)
+{
+ uint32_t mask, temp, our_int, status;
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+
+ /* check whether it's our interrupt */
+ if (!UNM_IS_MSI_FAMILY(adapter)) {
+
+ /* Legacy Interrupt case */
+ adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
+ &status);
+
+ if (!(status & adapter->legacy_intr.int_vec_bit)) {
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ return (-1);
+ }
+
+ if (adapter->ahw.revision_id >= NX_P3_B1) {
+ adapter->unm_nic_pci_read_immediate(adapter,
+ ISR_INT_STATE_REG, &temp);
+ if (!ISR_IS_LEGACY_INTR_TRIGGERED(temp)) {
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ return (-1);
+ }
+ } else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ our_int = adapter->unm_nic_pci_read_normalize(adapter,
+ CRB_INT_VECTOR);
+
+ /* FIXME: Assumes pci_func is same as ctx */
+ if ((our_int & (0x80 << adapter->portnum)) == 0) {
+ if (our_int != 0) {
+ /* not our interrupt */
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ return (-1);
+ }
+ }
+ temp = our_int & ~((u32)(0x80 << adapter->portnum));
+ adapter->unm_nic_pci_write_normalize(adapter,
+ CRB_INT_VECTOR, temp);
+ }
+
+ if (adapter->fw_major < 4)
+ unm_nic_disable_int(adapter);
+
+ /* claim interrupt */
+ temp = 0xffffffff;
+ adapter->unm_nic_pci_write_immediate(adapter,
+ adapter->legacy_intr.tgt_status_reg, &temp);
+
+ adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
+ &mask);
+
+ /*
+ * Read again to make sure the legacy interrupt message got
+ * flushed out
+ */
+ adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
+ &mask);
+ } else if (adapter->flags & UNM_NIC_MSI_ENABLED) {
+ /* clear interrupt */
+ temp = 0xffffffff;
+ adapter->unm_nic_pci_write_immediate(adapter,
+ msi_tgt_status[adapter->ahw.pci_func], &temp);
+ }
+
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ return (0);
+}
+
+static void
+unm_nic_enable_int(unm_adapter *adapter)
+{
+ u32 temp = 1;
+
+ adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
+ &temp, 4);
+
+ if (!UNM_IS_MSI_FAMILY(adapter)) {
+ u32 mask = 0xfbff;
+
+ adapter->unm_nic_pci_write_immediate(adapter,
+ adapter->legacy_intr.tgt_mask_reg, &mask);
+ }
+}
+
+static void
+unm_free_hw_resources(unm_adapter *adapter)
+{
+ unm_recv_context_t *recv_ctx;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ int ctx, ring;
+
+ if (adapter->context_alloced == 1) {
+ netxen_destroy_rxtx(adapter);
+ adapter->context_alloced = 0;
+ }
+
+ if (adapter->ctxDesc != NULL) {
+ unm_pci_free_consistent(&adapter->ctxDesc_dma_handle,
+ &adapter->ctxDesc_acc_handle);
+ adapter->ctxDesc = NULL;
+ }
+
+ if (adapter->ahw.cmdDescHead != NULL) {
+ unm_pci_free_consistent(&adapter->ahw.cmd_desc_dma_handle,
+ &adapter->ahw.cmd_desc_acc_handle);
+ adapter->ahw.cmdDesc_physAddr = NULL;
+ adapter->ahw.cmdDescHead = NULL;
+ }
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+
+ if (rcv_desc->desc_head != NULL) {
+ unm_pci_free_consistent(
+ &rcv_desc->rx_desc_dma_handle,
+ &rcv_desc->rx_desc_acc_handle);
+ rcv_desc->desc_head = NULL;
+ rcv_desc->phys_addr = NULL;
+ }
+ }
+
+ if (recv_ctx->rcvStatusDescHead != NULL) {
+ unm_pci_free_consistent(
+ &recv_ctx->status_desc_dma_handle,
+ &recv_ctx->status_desc_acc_handle);
+ recv_ctx->rcvStatusDesc_physAddr = NULL;
+ recv_ctx->rcvStatusDescHead = NULL;
+ }
+ }
+}
+
+static void
+cleanup_adapter(struct unm_adapter_s *adapter)
+{
+ if (adapter->cmd_buf_arr != NULL)
+ kmem_free(adapter->cmd_buf_arr,
+ sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount);
+
+ ddi_regs_map_free(&(adapter->regs_handle));
+ ddi_regs_map_free(&(adapter->db_handle));
+ kmem_free(adapter, sizeof (unm_adapter));
+
+}
+
+void
+unm_nic_remove(unm_adapter *adapter)
+{
+ unm_recv_context_t *recv_ctx;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ int ctx, ring;
+
+ mac_link_update(adapter->mach, LINK_STATE_DOWN);
+ unm_nic_stop_port(adapter);
+
+ if (adapter->interrupt_crb) {
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ unm_nic_disable_int(adapter);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ }
+ (void) untimeout(adapter->watchdog_timer);
+
+ unm_free_hw_resources(adapter);
+ unm_free_tx_buffers(adapter);
+ unm_free_tx_dmahdl(adapter);
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+ if (rcv_desc->rx_buf_pool != NULL)
+ unm_destroy_rx_ring(rcv_desc);
+ }
+ }
+
+ if (adapter->portnum == 0)
+ unm_free_dummy_dma(adapter);
+
+ unm_destroy_intr(adapter);
+
+ ddi_set_driver_private(adapter->dip, NULL);
+ cleanup_adapter(adapter);
+}
+
+static int
+init_firmware(unm_adapter *adapter)
+{
+ uint32_t state = 0, loops = 0, tempout;
+
+ /* Window 1 call */
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ state = adapter->unm_nic_pci_read_normalize(adapter, CRB_CMDPEG_STATE);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ if (state == PHAN_INITIALIZE_ACK)
+ return (0);
+
+ while (state != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
+ drv_usecwait(100);
+ /* Window 1 call */
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ state = adapter->unm_nic_pci_read_normalize(adapter,
+ CRB_CMDPEG_STATE);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ loops++;
+ }
+
+ if (loops >= 200000) {
+ cmn_err(CE_WARN, "%s%d: CmdPeg init incomplete:%x\n",
+ adapter->name, adapter->instance, state);
+ return (-EIO);
+ }
+
+ /* Window 1 call */
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ tempout = INTR_SCHEME_PERPORT;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_CAPABILITIES_HOST,
+ &tempout, 4);
+ tempout = MSI_MODE_MULTIFUNC;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_MSI_MODE_HOST,
+ &tempout, 4);
+ tempout = MPORT_MULTI_FUNCTION_MODE;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_MPORT_MODE, &tempout, 4);
+ tempout = PHAN_INITIALIZE_ACK;
+ adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE, &tempout, 4);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ return (0);
+}
+
+/*
+ * Utility to synchronize with receive peg.
+ * Returns 0 on sucess
+ * -EIO on error
+ */
+int
+receive_peg_ready(struct unm_adapter_s *adapter)
+{
+ uint32_t state = 0;
+ int loops = 0, err = 0;
+
+ /* Window 1 call */
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ state = adapter->unm_nic_pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 20000)) {
+ drv_usecwait(100);
+ /* Window 1 call */
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ state = adapter->unm_nic_pci_read_normalize(adapter,
+ CRB_RCVPEG_STATE);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ loops++;
+ }
+
+ if (loops >= 20000) {
+ cmn_err(CE_WARN, "Receive Peg initialization incomplete 0x%x\n",
+ state);
+ err = -EIO;
+ }
+
+ return (err);
+}
+
+/*
+ * check if the firmware has been downloaded and ready to run and
+ * setup the address for the descriptors in the adapter
+ */
+static int
+unm_nic_hw_resources(unm_adapter *adapter)
+{
+ hardware_context *hw = &adapter->ahw;
+ void *addr;
+ int err;
+ int ctx, ring;
+ unm_recv_context_t *recv_ctx;
+ unm_rcv_desc_ctx_t *rcv_desc;
+ ddi_dma_cookie_t cookie;
+ int size;
+
+ if (err = receive_peg_ready(adapter))
+ return (err);
+
+ size = (sizeof (RingContext) + sizeof (uint32_t));
+
+ err = unm_pci_alloc_consistent(adapter,
+ size, (caddr_t *)&addr, &cookie,
+ &adapter->ctxDesc_dma_handle,
+ &adapter->ctxDesc_acc_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Failed to allocate HW context\n");
+ return (err);
+ }
+
+ adapter->ctxDesc_physAddr = cookie.dmac_laddress;
+
+ (void) memset(addr, 0, sizeof (RingContext));
+
+ adapter->ctxDesc = (RingContext *) addr;
+ adapter->ctxDesc->CtxId = adapter->portnum;
+ adapter->ctxDesc->CMD_CONSUMER_OFFSET =
+ adapter->ctxDesc_physAddr + sizeof (RingContext);
+ adapter->cmdConsumer =
+ (uint32_t *)(uintptr_t)(((char *)addr) + sizeof (RingContext));
+
+ ASSERT(!((unsigned long)adapter->ctxDesc_physAddr & 0x3f));
+
+ /*
+ * Allocate command descriptor ring.
+ */
+ size = (sizeof (cmdDescType0_t) * adapter->MaxTxDescCount);
+ err = unm_pci_alloc_consistent(adapter,
+ size, (caddr_t *)&addr, &cookie,
+ &hw->cmd_desc_dma_handle,
+ &hw->cmd_desc_acc_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Failed to allocate cmd desc ring\n");
+ return (err);
+ }
+
+ hw->cmdDesc_physAddr = cookie.dmac_laddress;
+ hw->cmdDescHead = (cmdDescType0_t *)addr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ size = (sizeof (statusDesc_t)* adapter->MaxRxDescCount);
+ err = unm_pci_alloc_consistent(adapter,
+ size, (caddr_t *)&addr,
+ &recv_ctx->status_desc_dma_cookie,
+ &recv_ctx->status_desc_dma_handle,
+ &recv_ctx->status_desc_acc_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Failed to allocate sts desc ring\n");
+ goto free_cmd_desc;
+ }
+
+ (void) memset(addr, 0, size);
+ recv_ctx->rcvStatusDesc_physAddr =
+ recv_ctx->status_desc_dma_cookie.dmac_laddress;
+ recv_ctx->rcvStatusDescHead = (statusDesc_t *)addr;
+
+ /* rds rings */
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rcv_desc = &recv_ctx->rcv_desc[ring];
+
+ size = (sizeof (rcvDesc_t) * adapter->MaxRxDescCount);
+ err = unm_pci_alloc_consistent(adapter,
+ size, (caddr_t *)&addr,
+ &rcv_desc->rx_desc_dma_cookie,
+ &rcv_desc->rx_desc_dma_handle,
+ &rcv_desc->rx_desc_acc_handle);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Failed to allocate "
+ "rx desc ring %d\n", ring);
+ goto free_status_desc;
+ }
+
+ rcv_desc->phys_addr =
+ rcv_desc->rx_desc_dma_cookie.dmac_laddress;
+ rcv_desc->desc_head = (rcvDesc_t *)addr;
+ }
+ }
+
+ if (err = netxen_create_rxtx(adapter))
+ goto free_statusrx_desc;
+ adapter->context_alloced = 1;
+
+ return (DDI_SUCCESS);
+
+free_statusrx_desc:
+free_status_desc:
+free_cmd_desc:
+ unm_free_hw_resources(adapter);
+
+ return (err);
+}
+
+void unm_desc_dma_sync(ddi_dma_handle_t handle, uint_t start, uint_t count,
+ uint_t range, uint_t unit_size, uint_t direction)
+{
+ if ((start + count) < range) {
+ (void) ddi_dma_sync(handle, start * unit_size,
+ count * unit_size, direction);
+ } else {
+ (void) ddi_dma_sync(handle, start * unit_size, 0, direction);
+ (void) ddi_dma_sync(handle, 0,
+ (start + count - range) * unit_size, DDI_DMA_SYNC_FORCPU);
+ }
+}
+
+static uint32_t crb_cmd_producer[4] = { CRB_CMD_PRODUCER_OFFSET,
+ CRB_CMD_PRODUCER_OFFSET_1, CRB_CMD_PRODUCER_OFFSET_2,
+ CRB_CMD_PRODUCER_OFFSET_3 };
+
+static uint32_t crb_cmd_consumer[4] = { CRB_CMD_CONSUMER_OFFSET,
+ CRB_CMD_CONSUMER_OFFSET_1, CRB_CMD_CONSUMER_OFFSET_2,
+ CRB_CMD_CONSUMER_OFFSET_3 };
+
+void
+unm_nic_update_cmd_producer(struct unm_adapter_s *adapter,
+ uint32_t crb_producer)
+{
+ int data = crb_producer;
+
+ if (adapter->crb_addr_cmd_producer) {
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_write_wx(adapter,
+ adapter->crb_addr_cmd_producer, &data, 4);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ }
+}
+
+static void
+unm_nic_update_cmd_consumer(struct unm_adapter_s *adapter,
+ uint32_t crb_producer)
+{
+ int data = crb_producer;
+
+ if (adapter->crb_addr_cmd_consumer)
+ adapter->unm_nic_hw_write_wx(adapter,
+ adapter->crb_addr_cmd_consumer, &data, 4);
+}
+
+/*
+ * Looks for type of packet and sets opcode accordingly
+ * so that checksum offload can be used.
+ */
+static void
+unm_tx_csum(cmdDescType0_t *desc, mblk_t *mp, pktinfo_t *pktinfo)
+{
+ if (pktinfo->mac_hlen == sizeof (struct ether_vlan_header))
+ desc->u1.s1.flags = FLAGS_VLAN_TAGGED;
+
+ if (pktinfo->etype == htons(ETHERTYPE_IP)) {
+ uint32_t start, flags;
+
+ hcksum_retrieve(mp, NULL, NULL, &start, NULL, NULL, NULL,
+ &flags);
+ if ((flags & (HCK_FULLCKSUM | HCK_IPV4_HDRCKSUM)) == 0)
+ return;
+
+ /*
+ * For TCP/UDP, ask hardware to do both IP header and
+ * full checksum, even if stack has already done one or
+ * the other. Hardware will always get it correct even
+ * if stack has already done it.
+ */
+ switch (pktinfo->l4_proto) {
+ case IPPROTO_TCP:
+ desc->u1.s1.opcode = TX_TCP_PKT;
+ break;
+ case IPPROTO_UDP:
+ desc->u1.s1.opcode = TX_UDP_PKT;
+ break;
+ default:
+ /* Must be here with HCK_IPV4_HDRCKSUM */
+ desc->u1.s1.opcode = TX_IP_PKT;
+ return;
+ }
+
+ desc->u1.s1.ipHdrOffset = pktinfo->mac_hlen;
+ desc->u1.s1.tcpHdrOffset = pktinfo->mac_hlen + pktinfo->ip_hlen;
+ }
+}
+
+/*
+ * For IP/UDP/TCP checksum offload, this checks for MAC+IP header in one
+ * contiguous block ending at 8 byte aligned address as required by hardware.
+ * Caller assumes pktinfo->total_len will be updated by this function and
+ * if pktinfo->etype is set to 0, it will need to linearize the mblk and
+ * invoke unm_update_pkt_info() to determine ethertype, IP header len and
+ * protocol.
+ */
+static boolean_t
+unm_get_pkt_info(mblk_t *mp, pktinfo_t *pktinfo)
+{
+ mblk_t *bp;
+ ushort_t type;
+
+ (void) memset(pktinfo, 0, sizeof (pktinfo_t));
+
+ for (bp = mp; bp != NULL; bp = bp->b_cont) {
+ if (MBLKL(bp) == 0)
+ continue;
+ pktinfo->mblk_no++;
+ pktinfo->total_len += MBLKL(bp);
+ }
+
+ if (MBLKL(mp) < (sizeof (struct ether_header) + sizeof (ipha_t)))
+ return (B_FALSE);
+
+ /*
+ * We just need non 1 byte aligned address, since ether_type is
+ * ushort.
+ */
+ if ((uintptr_t)mp->b_rptr & 1)
+ return (B_FALSE);
+
+ type = ((struct ether_header *)(uintptr_t)mp->b_rptr)->ether_type;
+ if (type == htons(ETHERTYPE_VLAN)) {
+ if (MBLKL(mp) < (sizeof (struct ether_vlan_header) +
+ sizeof (ipha_t)))
+ return (B_FALSE);
+ type = ((struct ether_vlan_header *) \
+ (uintptr_t)mp->b_rptr)->ether_type;
+ pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
+ } else {
+ pktinfo->mac_hlen = sizeof (struct ether_header);
+ }
+ pktinfo->etype = type;
+
+ if (pktinfo->etype == htons(ETHERTYPE_IP)) {
+ uchar_t *ip_off = mp->b_rptr + pktinfo->mac_hlen;
+
+ pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ip_off);
+ pktinfo->l4_proto =
+ ((ipha_t *)(uintptr_t)ip_off)->ipha_protocol;
+
+ /* IP header not aligned to quadward boundary? */
+ if ((unsigned long)(ip_off + pktinfo->ip_hlen) % 8 != 0)
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+static void
+unm_update_pkt_info(char *ptr, pktinfo_t *pktinfo)
+{
+ ushort_t type;
+
+ type = ((struct ether_header *)(uintptr_t)ptr)->ether_type;
+ if (type == htons(ETHERTYPE_VLAN)) {
+ type = ((struct ether_vlan_header *)(uintptr_t)ptr)->ether_type;
+ pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
+ } else {
+ pktinfo->mac_hlen = sizeof (struct ether_header);
+ }
+ pktinfo->etype = type;
+
+ if (pktinfo->etype == htons(ETHERTYPE_IP)) {
+ char *ipp = ptr + pktinfo->mac_hlen;
+
+ pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ipp);
+ pktinfo->l4_proto = ((ipha_t *)(uintptr_t)ipp)->ipha_protocol;
+ }
+}
+
+static boolean_t
+unm_send_copy(struct unm_adapter_s *adapter, mblk_t *mp, pktinfo_t *pktinfo)
+{
+ hardware_context *hw;
+ u32 producer = 0;
+ cmdDescType0_t *hwdesc;
+ struct unm_cmd_buffer *pbuf = NULL;
+ u32 mblen;
+ int no_of_desc = 1;
+ int MaxTxDescCount;
+ mblk_t *bp;
+ char *txb;
+
+ hw = &adapter->ahw;
+ MaxTxDescCount = adapter->MaxTxDescCount;
+
+ UNM_SPIN_LOCK(&adapter->tx_lock);
+ membar_enter();
+
+ if (find_diff_among(adapter->cmdProducer, adapter->lastCmdConsumer,
+ MaxTxDescCount) <= 2) {
+ adapter->stats.outofcmddesc++;
+ adapter->resched_needed = 1;
+ membar_exit();
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+ return (B_FALSE);
+ }
+ adapter->freecmds -= no_of_desc;
+
+ producer = adapter->cmdProducer;
+
+ adapter->cmdProducer = get_index_range(adapter->cmdProducer,
+ MaxTxDescCount, no_of_desc);
+
+ hwdesc = &hw->cmdDescHead[producer];
+ (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
+ pbuf = &adapter->cmd_buf_arr[producer];
+
+ pbuf->msg = NULL;
+ pbuf->head = NULL;
+ pbuf->tail = NULL;
+
+ txb = pbuf->dma_area.vaddr;
+
+ for (bp = mp; bp != NULL; bp = bp->b_cont) {
+ if ((mblen = MBLKL(bp)) == 0)
+ continue;
+ bcopy(bp->b_rptr, txb, mblen);
+ txb += mblen;
+ }
+
+ /*
+ * Determine metadata if not previously done due to fragmented mblk.
+ */
+ if (pktinfo->etype == 0)
+ unm_update_pkt_info(pbuf->dma_area.vaddr, pktinfo);
+
+ (void) ddi_dma_sync(pbuf->dma_area.dma_hdl,
+ 0, pktinfo->total_len, DDI_DMA_SYNC_FORDEV);
+
+ /* hwdesc->u1.s1.tcpHdrOffset = 0; */
+ /* hwdesc->mss = 0; */
+ hwdesc->u1.s1.opcode = TX_ETHER_PKT;
+ hwdesc->u3.s1.port = adapter->portnum;
+ hwdesc->u3.s1.ctx_id = adapter->portnum;
+
+ hwdesc->u6.s1.buffer1Length = pktinfo->total_len;
+ hwdesc->u5.AddrBuffer1 = pbuf->dma_area.dma_addr;
+ hwdesc->u1.s1.numOfBuffers = 1;
+ hwdesc->u1.s1.totalLength = pktinfo->total_len;
+
+ unm_tx_csum(hwdesc, mp, pktinfo);
+
+ unm_desc_dma_sync(hw->cmd_desc_dma_handle,
+ producer,
+ no_of_desc,
+ MaxTxDescCount,
+ sizeof (cmdDescType0_t),
+ DDI_DMA_SYNC_FORDEV);
+
+ hw->cmdProducer = adapter->cmdProducer;
+ unm_nic_update_cmd_producer(adapter, adapter->cmdProducer);
+
+ adapter->stats.txbytes += pktinfo->total_len;
+ adapter->stats.xmitfinished++;
+ adapter->stats.txcopyed++;
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+
+ freemsg(mp);
+ return (B_TRUE);
+}
+
+/* Should be called with adapter->tx_lock held. */
+static void
+unm_return_dma_handle(unm_adapter *adapter, unm_dmah_node_t *head,
+ unm_dmah_node_t *tail, uint32_t num)
+{
+ ASSERT(tail != NULL);
+ tail->next = adapter->dmahdl_pool;
+ adapter->dmahdl_pool = head;
+ adapter->freehdls += num;
+}
+
+static unm_dmah_node_t *
+unm_reserve_dma_handle(unm_adapter* adapter)
+{
+ unm_dmah_node_t *dmah = NULL;
+
+ dmah = adapter->dmahdl_pool;
+ if (dmah != NULL) {
+ adapter->dmahdl_pool = dmah->next;
+ dmah->next = NULL;
+ adapter->freehdls--;
+ membar_exit();
+ }
+
+ return (dmah);
+}
+
+static boolean_t
+unm_send_mapped(struct unm_adapter_s *adapter, mblk_t *mp, pktinfo_t *pktinfo)
+{
+ hardware_context *hw;
+ u32 producer = 0;
+ u32 saved_producer = 0;
+ cmdDescType0_t *hwdesc;
+ struct unm_cmd_buffer *pbuf = NULL;
+ int no_of_desc;
+ int k;
+ int MaxTxDescCount;
+ mblk_t *bp;
+
+ unm_dmah_node_t *dmah, *head = NULL, *tail = NULL, *hdlp;
+ ddi_dma_cookie_t cookie[MAX_COOKIES_PER_CMD + 1];
+ int ret, i;
+ uint32_t hdl_reserved = 0;
+ uint32_t mblen;
+ uint32_t ncookies, index = 0, total_cookies = 0;
+
+ MaxTxDescCount = adapter->MaxTxDescCount;
+
+ UNM_SPIN_LOCK(&adapter->tx_lock);
+
+ /* bind all the mblks of the packet first */
+ for (bp = mp; bp != NULL; bp = bp->b_cont) {
+ mblen = MBLKL(bp);
+ if (mblen == 0)
+ continue;
+
+ dmah = unm_reserve_dma_handle(adapter);
+ if (dmah == NULL) {
+ adapter->stats.outoftxdmahdl++;
+ goto err_map;
+ }
+
+ ret = ddi_dma_addr_bind_handle(dmah->dmahdl,
+ NULL, (caddr_t)bp->b_rptr, mblen,
+ DDI_DMA_STREAMING | DDI_DMA_WRITE,
+ DDI_DMA_DONTWAIT, NULL, &cookie[index], &ncookies);
+
+ if (ret != DDI_DMA_MAPPED)
+ goto err_map;
+
+ if (tail == NULL) {
+ head = tail = dmah;
+ } else {
+ tail->next = dmah;
+ tail = dmah;
+ }
+ hdl_reserved++;
+
+ total_cookies += ncookies;
+ if (total_cookies > MAX_COOKIES_PER_CMD) {
+ dmah = NULL;
+ goto err_map;
+ }
+
+ if (index == 0) {
+ size_t hsize = cookie[0].dmac_size;
+
+ /*
+ * For TCP/UDP packets with checksum offload,
+ * MAC/IP headers need to be contiguous. Otherwise,
+ * there must be at least 16 bytes in the first
+ * descriptor.
+ */
+ if ((pktinfo->l4_proto == IPPROTO_TCP) ||
+ (pktinfo->l4_proto == IPPROTO_UDP)) {
+ if (hsize < (pktinfo->mac_hlen +
+ pktinfo->ip_hlen)) {
+ dmah = NULL;
+ goto err_map;
+ }
+ } else {
+ if (hsize < 16) {
+ dmah = NULL;
+ goto err_map;
+ }
+ }
+ }
+
+ index++;
+ ncookies--;
+ for (i = 0; i < ncookies; i++, index++)
+ ddi_dma_nextcookie(dmah->dmahdl, &cookie[index]);
+ }
+
+ dmah = NULL;
+ hw = &adapter->ahw;
+ no_of_desc = (total_cookies + 3) >> 2;
+
+ membar_enter();
+ if (find_diff_among(adapter->cmdProducer, adapter->lastCmdConsumer,
+ MaxTxDescCount) < no_of_desc+2) {
+ /*
+ * If we are going to be trying the copy path, no point
+ * scheduling an upcall when Tx resources are freed.
+ */
+ if (pktinfo->total_len > adapter->maxmtu) {
+ adapter->stats.outofcmddesc++;
+ adapter->resched_needed = 1;
+ }
+ membar_exit();
+ goto err_alloc_desc;
+ }
+ adapter->freecmds -= no_of_desc;
+
+ /* Copy the descriptors into the hardware */
+ producer = adapter->cmdProducer;
+ saved_producer = producer;
+ hwdesc = &hw->cmdDescHead[producer];
+ (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
+ pbuf = &adapter->cmd_buf_arr[producer];
+
+ pbuf->msg = mp;
+ pbuf->head = head;
+ pbuf->tail = tail;
+
+ hwdesc->u1.s1.numOfBuffers = total_cookies;
+ hwdesc->u1.s1.opcode = TX_ETHER_PKT;
+ hwdesc->u3.s1.port = adapter->portnum;
+ /* hwdesc->u1.s1.tcpHdrOffset = 0; */
+ /* hwdesc->mss = 0; */
+ hwdesc->u3.s1.ctx_id = adapter->portnum;
+ hwdesc->u1.s1.totalLength = pktinfo->total_len;
+ unm_tx_csum(hwdesc, mp, pktinfo);
+
+ for (i = k = 0; i < total_cookies; i++) {
+ if (k == 4) {
+ /* Move to the next descriptor */
+ k = 0;
+ producer = get_next_index(producer, MaxTxDescCount);
+ hwdesc = &hw->cmdDescHead[producer];
+ (void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
+ }
+
+ switch (k) {
+ case 0:
+ hwdesc->u6.s1.buffer1Length = cookie[i].dmac_size;
+ hwdesc->u5.AddrBuffer1 = cookie[i].dmac_laddress;
+ break;
+ case 1:
+ hwdesc->u6.s1.buffer2Length = cookie[i].dmac_size;
+ hwdesc->u2.AddrBuffer2 = cookie[i].dmac_laddress;
+ break;
+ case 2:
+ hwdesc->u6.s1.buffer3Length = cookie[i].dmac_size;
+ hwdesc->u4.AddrBuffer3 = cookie[i].dmac_laddress;
+ break;
+ case 3:
+ hwdesc->u6.s1.buffer4Length = cookie[i].dmac_size;
+ hwdesc->u7.AddrBuffer4 = cookie[i].dmac_laddress;
+ break;
+ }
+ k++;
+ }
+
+ unm_desc_dma_sync(hw->cmd_desc_dma_handle, saved_producer, no_of_desc,
+ MaxTxDescCount, sizeof (cmdDescType0_t), DDI_DMA_SYNC_FORDEV);
+
+ adapter->cmdProducer = get_next_index(producer, MaxTxDescCount);
+ hw->cmdProducer = adapter->cmdProducer;
+ unm_nic_update_cmd_producer(adapter, adapter->cmdProducer);
+
+ adapter->stats.txbytes += pktinfo->total_len;
+ adapter->stats.xmitfinished++;
+ adapter->stats.txmapped++;
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+ return (B_TRUE);
+
+err_alloc_desc:
+err_map:
+
+ hdlp = head;
+ while (hdlp != NULL) {
+ (void) ddi_dma_unbind_handle(hdlp->dmahdl);
+ hdlp = hdlp->next;
+ }
+
+ /*
+ * add the reserved but bind failed one to the list to be returned
+ */
+ if (dmah != NULL) {
+ if (tail == NULL)
+ head = tail = dmah;
+ else {
+ tail->next = dmah;
+ tail = dmah;
+ }
+ hdl_reserved++;
+ }
+
+ if (head != NULL)
+ unm_return_dma_handle(adapter, head, tail, hdl_reserved);
+
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+ return (B_FALSE);
+}
+
+static boolean_t
+unm_nic_xmit_frame(unm_adapter *adapter, mblk_t *mp)
+{
+ pktinfo_t pktinfo;
+ boolean_t status = B_FALSE, send_mapped;
+
+ adapter->stats.xmitcalled++;
+
+ send_mapped = unm_get_pkt_info(mp, &pktinfo);
+
+ if (pktinfo.total_len <= adapter->tx_bcopy_threshold ||
+ pktinfo.mblk_no >= MAX_BUFFERS_PER_CMD)
+ send_mapped = B_FALSE;
+
+ if (send_mapped == B_TRUE)
+ status = unm_send_mapped(adapter, mp, &pktinfo);
+
+ if (status != B_TRUE) {
+ if (pktinfo.total_len <= adapter->maxmtu)
+ return (unm_send_copy(adapter, mp, &pktinfo));
+
+ /* message too large */
+ freemsg(mp);
+ adapter->stats.txdropped++;
+ status = B_TRUE;
+ }
+
+ return (status);
+}
+
+static int
+unm_nic_check_temp(struct unm_adapter_s *adapter)
+{
+ uint32_t temp, temp_state, temp_val;
+ int rv = 0;
+
+ if ((adapter->ahw.revision_id == NX_P3_A2) ||
+ (adapter->ahw.revision_id == NX_P3_A0))
+ return (0);
+
+ temp = adapter->unm_nic_pci_read_normalize(adapter, CRB_TEMP_STATE);
+
+ temp_state = nx_get_temp_state(temp);
+ temp_val = nx_get_temp_val(temp);
+
+ if (temp_state == NX_TEMP_PANIC) {
+ cmn_err(CE_WARN, "%s: Device temperature %d C exceeds "
+ "maximum allowed, device has been shut down\n",
+ unm_nic_driver_name, temp_val);
+ rv = 1;
+ } else if (temp_state == NX_TEMP_WARN) {
+ if (adapter->temp == NX_TEMP_NORMAL) {
+ cmn_err(CE_WARN, "%s: Device temperature %d C exceeds"
+ "operating range. Immediate action needed.\n",
+ unm_nic_driver_name, temp_val);
+ }
+ } else {
+ if (adapter->temp == NX_TEMP_WARN) {
+ cmn_err(CE_WARN, "%s: Device temperature is now %d "
+ "degrees C in normal range.\n",
+ unm_nic_driver_name, temp_val);
+ }
+ }
+
+ adapter->temp = temp_state;
+ return (rv);
+}
+
+static void
+unm_watchdog(unsigned long v)
+{
+ unm_adapter *adapter = (unm_adapter *)v;
+
+ if ((adapter->portnum == 0) && unm_nic_check_temp(adapter)) {
+ /*
+ * We return without turning on the netdev queue as there
+ * was an overheated device
+ */
+ return;
+ }
+
+ unm_nic_handle_phy_intr(adapter);
+
+ /*
+ * This function schedules a call for itself.
+ */
+ adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
+ (void *)adapter, 2 * drv_usectohz(1000000));
+
+}
+
+static void unm_nic_clear_stats(unm_adapter *adapter)
+{
+ (void) memset(&adapter->stats, 0, sizeof (adapter->stats));
+}
+
+static void
+unm_nic_poll(unm_adapter *adapter)
+{
+ int work_done, tx_complete;
+
+ adapter->stats.polled++;
+
+loop:
+ tx_complete = unm_process_cmd_ring(adapter);
+ work_done = unm_process_rcv_ring(adapter, NX_RX_MAXBUFS);
+ if ((!tx_complete) || (!(work_done < NX_RX_MAXBUFS)))
+ goto loop;
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ unm_nic_enable_int(adapter);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+}
+
+/* ARGSUSED */
+uint_t
+unm_intr(caddr_t data, caddr_t arg)
+{
+ unm_adapter *adapter = (unm_adapter *)(uintptr_t)data;
+
+ if (unm_nic_clear_int(adapter))
+ return (DDI_INTR_UNCLAIMED);
+
+ unm_nic_poll(adapter);
+ return (DDI_INTR_CLAIMED);
+}
+
+/*
+ * This is invoked from receive isr. Due to the single threaded nature
+ * of the invocation, pool_lock acquisition is not neccesary to protect
+ * pool_list.
+ */
+static void
+unm_free_rx_buffer(unm_rcv_desc_ctx_t *rcv_desc, unm_rx_buffer_t *rx_buffer)
+{
+ /* mutex_enter(rcv_desc->pool_lock); */
+ rx_buffer->next = rcv_desc->pool_list;
+ rcv_desc->pool_list = rx_buffer;
+ rcv_desc->rx_buf_free++;
+ /* mutex_exit(rcv_desc->pool_lock); */
+}
+
+/*
+ * unm_process_rcv() send the received packet to the protocol stack.
+ */
+static mblk_t *
+unm_process_rcv(unm_adapter *adapter, statusDesc_t *desc)
+{
+ unm_recv_context_t *recv_ctx = &(adapter->recv_ctx[0]);
+ unm_rx_buffer_t *rx_buffer;
+ mblk_t *mp;
+ u32 desc_ctx = desc->u1.s1.type;
+ unm_rcv_desc_ctx_t *rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
+ u32 pkt_length = desc->u1.s1.totalLength;
+ int poff = desc->u1.s1.pkt_offset;
+ int index, cksum_flags, docopy;
+ int index_lo = desc->u1.s1.referenceHandle_lo;
+ char *vaddr;
+
+ index = ((desc->u1.s1.referenceHandle_hi << 4) | index_lo);
+
+ rx_buffer = index2rxbuf(rcv_desc, index);
+
+ if (rx_buffer == NULL) {
+ cmn_err(CE_WARN, "\r\nNULL rx_buffer idx=%d", index);
+ return (NULL);
+ }
+ vaddr = (char *)rx_buffer->dma_info.vaddr;
+ if (vaddr == NULL) {
+ cmn_err(CE_WARN, "\r\nNULL vaddr");
+ return (NULL);
+ }
+ rcv_desc->rx_desc_handled++;
+ rcv_desc->rx_buf_card--;
+
+ (void) ddi_dma_sync(rx_buffer->dma_info.dma_hdl, 0,
+ pkt_length + poff + (adapter->ahw.cut_through ? 0 :
+ IP_ALIGNMENT_BYTES), DDI_DMA_SYNC_FORCPU);
+
+ /*
+ * Copy packet into new allocated message buffer, if pkt_length
+ * is below copy threshold.
+ */
+ docopy = (pkt_length <= adapter->rx_bcopy_threshold) ? 1 : 0;
+
+ /*
+ * If card is running out of rx buffers, then attempt to allocate
+ * new mblk so we can feed this rx buffer back to card (we
+ * _could_ look at what's pending on free and recycle lists).
+ */
+ if (rcv_desc->rx_buf_card < NX_RX_THRESHOLD) {
+ docopy = 1;
+ adapter->stats.rxbufshort++;
+ }
+
+ if (docopy == 1) {
+ if ((mp = allocb(pkt_length + IP_ALIGNMENT_BYTES, 0)) == NULL) {
+ adapter->stats.allocbfailed++;
+ goto freebuf;
+ }
+
+ mp->b_rptr += IP_ALIGNMENT_BYTES;
+ vaddr += poff;
+ bcopy(vaddr, mp->b_rptr, pkt_length);
+ adapter->stats.rxcopyed++;
+ unm_free_rx_buffer(rcv_desc, rx_buffer);
+ } else {
+ mp = (mblk_t *)rx_buffer->mp;
+ if (mp == NULL) {
+ mp = desballoc(rx_buffer->dma_info.vaddr,
+ rcv_desc->dma_size, 0, &rx_buffer->rx_recycle);
+ if (mp == NULL) {
+ adapter->stats.desballocfailed++;
+ goto freebuf;
+ }
+ rx_buffer->mp = mp;
+ }
+ mp->b_rptr += poff;
+ adapter->stats.rxmapped++;
+ }
+
+ mp->b_wptr = (uchar_t *)((unsigned long)mp->b_rptr + pkt_length);
+
+ if (desc->u1.s1.status == STATUS_CKSUM_OK) {
+ adapter->stats.csummed++;
+ cksum_flags =
+ HCK_FULLCKSUM_OK | HCK_IPV4_HDRCKSUM | HCK_FULLCKSUM;
+ } else {
+ cksum_flags = 0;
+ }
+ (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, 0, cksum_flags, 0);
+
+ adapter->stats.no_rcv++;
+ adapter->stats.rxbytes += pkt_length;
+ adapter->stats.uphappy++;
+
+ return (mp);
+
+freebuf:
+ unm_free_rx_buffer(rcv_desc, rx_buffer);
+ return (NULL);
+}
+
+/* Process Receive status ring */
+static int
+unm_process_rcv_ring(unm_adapter *adapter, int max)
+{
+ unm_recv_context_t *recv_ctx = &(adapter->recv_ctx[0]);
+ statusDesc_t *desc_head = recv_ctx->rcvStatusDescHead;
+ statusDesc_t *desc = NULL;
+ uint32_t consumer, start;
+ int count = 0, ring;
+ mblk_t *mp;
+
+ start = consumer = recv_ctx->statusRxConsumer;
+
+ unm_desc_dma_sync(recv_ctx->status_desc_dma_handle, start, max,
+ adapter->MaxRxDescCount, sizeof (statusDesc_t),
+ DDI_DMA_SYNC_FORCPU);
+
+ while (count < max) {
+ desc = &desc_head[consumer];
+ if (!(desc->u1.s1.owner & STATUS_OWNER_HOST))
+ break;
+
+ mp = unm_process_rcv(adapter, desc);
+ desc->u1.s1.owner = STATUS_OWNER_PHANTOM;
+
+ consumer = (consumer + 1) % adapter->MaxRxDescCount;
+ count++;
+ if (mp != NULL)
+ mac_rx(adapter->mach, NULL, mp);
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ if (recv_ctx->rcv_desc[ring].rx_desc_handled > 0)
+ unm_post_rx_buffers_nodb(adapter, ring);
+ }
+
+ if (count) {
+ unm_desc_dma_sync(recv_ctx->status_desc_dma_handle, start,
+ count, adapter->MaxRxDescCount, sizeof (statusDesc_t),
+ DDI_DMA_SYNC_FORDEV);
+
+ /* update the consumer index in phantom */
+ recv_ctx->statusRxConsumer = consumer;
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_write_wx(adapter,
+ recv_ctx->host_sds_consumer, &consumer, 4);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ }
+
+ return (count);
+}
+
+/* Process Command status ring */
+static int
+unm_process_cmd_ring(struct unm_adapter_s *adapter)
+{
+ u32 last_consumer;
+ u32 consumer;
+ int count = 0;
+ struct unm_cmd_buffer *buffer;
+ int done;
+ unm_dmah_node_t *dmah, *head = NULL, *tail = NULL;
+ uint32_t free_hdls = 0;
+
+ (void) ddi_dma_sync(adapter->ctxDesc_dma_handle, sizeof (RingContext),
+ sizeof (uint32_t), DDI_DMA_SYNC_FORCPU);
+
+ last_consumer = adapter->lastCmdConsumer;
+ consumer = *(adapter->cmdConsumer);
+
+ while (last_consumer != consumer) {
+ buffer = &adapter->cmd_buf_arr[last_consumer];
+ if (buffer->head != NULL) {
+ dmah = buffer->head;
+ while (dmah != NULL) {
+ (void) ddi_dma_unbind_handle(dmah->dmahdl);
+ dmah = dmah->next;
+ free_hdls++;
+ }
+
+ if (head == NULL) {
+ head = buffer->head;
+ tail = buffer->tail;
+ } else {
+ tail->next = buffer->head;
+ tail = buffer->tail;
+ }
+
+ buffer->head = NULL;
+ buffer->tail = NULL;
+
+ if (buffer->msg != NULL) {
+ freemsg(buffer->msg);
+ buffer->msg = NULL;
+ }
+ }
+
+ last_consumer = get_next_index(last_consumer,
+ adapter->MaxTxDescCount);
+ if (++count > NX_MAX_TXCOMPS)
+ break;
+ }
+
+ if (count) {
+ int doresched;
+
+ UNM_SPIN_LOCK(&adapter->tx_lock);
+ adapter->lastCmdConsumer = last_consumer;
+ adapter->freecmds += count;
+ membar_exit();
+
+ doresched = adapter->resched_needed;
+ if (doresched)
+ adapter->resched_needed = 0;
+
+ if (head != NULL)
+ unm_return_dma_handle(adapter, head, tail, free_hdls);
+
+ UNM_SPIN_UNLOCK(&adapter->tx_lock);
+
+ if (doresched)
+ mac_tx_update(adapter->mach);
+ }
+
+ (void) ddi_dma_sync(adapter->ctxDesc_dma_handle, sizeof (RingContext),
+ sizeof (uint32_t), DDI_DMA_SYNC_FORCPU);
+
+ consumer = *(adapter->cmdConsumer);
+ done = (adapter->lastCmdConsumer == consumer);
+
+ return (done);
+}
+
+/*
+ * This is invoked from receive isr, and at initialization time when no
+ * rx buffers have been posted to card. Due to the single threaded nature
+ * of the invocation, pool_lock acquisition is not neccesary to protect
+ * pool_list.
+ */
+static unm_rx_buffer_t *
+unm_reserve_rx_buffer(unm_rcv_desc_ctx_t *rcv_desc)
+{
+ unm_rx_buffer_t *rx_buffer = NULL;
+
+ /* mutex_enter(rcv_desc->pool_lock); */
+ if (rcv_desc->rx_buf_free) {
+ rx_buffer = rcv_desc->pool_list;
+ rcv_desc->pool_list = rx_buffer->next;
+ rx_buffer->next = NULL;
+ rcv_desc->rx_buf_free--;
+ } else {
+ mutex_enter(rcv_desc->recycle_lock);
+
+ if (rcv_desc->rx_buf_recycle) {
+ rcv_desc->pool_list = rcv_desc->recycle_list;
+ rcv_desc->recycle_list = NULL;
+ rcv_desc->rx_buf_free += rcv_desc->rx_buf_recycle;
+ rcv_desc->rx_buf_recycle = 0;
+
+ rx_buffer = rcv_desc->pool_list;
+ rcv_desc->pool_list = rx_buffer->next;
+ rx_buffer->next = NULL;
+ rcv_desc->rx_buf_free--;
+ }
+
+ mutex_exit(rcv_desc->recycle_lock);
+ }
+
+ /* mutex_exit(rcv_desc->pool_lock); */
+ return (rx_buffer);
+}
+
+static void
+post_rx_doorbell(struct unm_adapter_s *adapter, uint32_t ringid, int count)
+{
+#define UNM_RCV_PEG_DB_ID 2
+#define UNM_RCV_PRODUCER_OFFSET 0
+ ctx_msg msg = {0};
+
+ /*
+ * Write a doorbell msg to tell phanmon of change in
+ * receive ring producer
+ */
+ msg.PegId = UNM_RCV_PEG_DB_ID;
+ msg.privId = 1;
+ msg.Count = count;
+ msg.CtxId = adapter->portnum;
+ msg.Opcode = UNM_RCV_PRODUCER(ringid);
+ dbwritel(*((__uint32_t *)&msg),
+ (void *)(DB_NORMALIZE(adapter, UNM_RCV_PRODUCER_OFFSET)));
+}
+
+static int
+unm_post_rx_buffers(struct unm_adapter_s *adapter, uint32_t ringid)
+{
+ unm_recv_context_t *recv_ctx = &(adapter->recv_ctx[0]);
+ unm_rcv_desc_ctx_t *rcv_desc = &recv_ctx->rcv_desc[ringid];
+ unm_rx_buffer_t *rx_buffer;
+ rcvDesc_t *pdesc;
+ int count;
+
+ for (count = 0; count < rcv_desc->MaxRxDescCount; count++) {
+ rx_buffer = unm_reserve_rx_buffer(rcv_desc);
+ if (rx_buffer != NULL) {
+ pdesc = &rcv_desc->desc_head[count];
+ pdesc->referenceHandle = rxbuf2index(rcv_desc,
+ rx_buffer);
+ pdesc->flags = ringid;
+ pdesc->bufferLength = rcv_desc->dma_size;
+ pdesc->AddrBuffer = rx_buffer->dma_info.dma_addr;
+ }
+ else
+ return (DDI_FAILURE);
+ }
+
+ rcv_desc->producer = count % rcv_desc->MaxRxDescCount;
+ count--;
+ unm_desc_dma_sync(rcv_desc->rx_desc_dma_handle,
+ 0, /* start */
+ count, /* count */
+ count, /* range */
+ sizeof (rcvDesc_t), /* unit_size */
+ DDI_DMA_SYNC_FORDEV); /* direction */
+
+ rcv_desc->rx_buf_card = rcv_desc->MaxRxDescCount;
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_write_wx(adapter, rcv_desc->host_rx_producer,
+ &count, 4);
+ if (adapter->fw_major < 4)
+ post_rx_doorbell(adapter, ringid, count);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ return (DDI_SUCCESS);
+}
+
+static void
+unm_post_rx_buffers_nodb(struct unm_adapter_s *adapter,
+ uint32_t ringid)
+{
+ unm_recv_context_t *recv_ctx = &(adapter->recv_ctx[0]);
+ unm_rcv_desc_ctx_t *rcv_desc = &recv_ctx->rcv_desc[ringid];
+ struct unm_rx_buffer *rx_buffer;
+ rcvDesc_t *pdesc;
+ int count, producer = rcv_desc->producer;
+ int last_producer = producer;
+
+ for (count = 0; count < rcv_desc->rx_desc_handled; count++) {
+ rx_buffer = unm_reserve_rx_buffer(rcv_desc);
+ if (rx_buffer != NULL) {
+ pdesc = &rcv_desc->desc_head[producer];
+ pdesc->referenceHandle = rxbuf2index(rcv_desc,
+ rx_buffer);
+ pdesc->flags = ringid;
+ pdesc->bufferLength = rcv_desc->dma_size;
+ pdesc->AddrBuffer = rx_buffer->dma_info.dma_addr;
+ } else {
+ adapter->stats.outofrxbuf++;
+ break;
+ }
+ producer = get_next_index(producer, rcv_desc->MaxRxDescCount);
+ }
+
+ /* if we did allocate buffers, then write the count to Phantom */
+ if (count) {
+ /* Sync rx ring, considering case for wrap around */
+ unm_desc_dma_sync(rcv_desc->rx_desc_dma_handle, last_producer,
+ count, rcv_desc->MaxRxDescCount, sizeof (rcvDesc_t),
+ DDI_DMA_SYNC_FORDEV);
+
+ rcv_desc->producer = producer;
+ rcv_desc->rx_desc_handled -= count;
+ rcv_desc->rx_buf_card += count;
+
+ producer = (producer - 1) % rcv_desc->MaxRxDescCount;
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ adapter->unm_nic_hw_write_wx(adapter,
+ rcv_desc->host_rx_producer, &producer, 4);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ }
+}
+
+int
+unm_nic_fill_statistics_128M(struct unm_adapter_s *adapter,
+ struct unm_statistics *unm_stats)
+{
+ void *addr;
+ if (adapter->ahw.board_type == UNM_NIC_XGBE) {
+ UNM_WRITE_LOCK(&adapter->adapter_lock);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_TX_BYTE_CNT,
+ &(unm_stats->tx_bytes));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_TX_FRAME_CNT,
+ &(unm_stats->tx_packets));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_RX_BYTE_CNT,
+ &(unm_stats->rx_bytes));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_RX_FRAME_CNT,
+ &(unm_stats->rx_packets));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_AGGR_ERROR_CNT,
+ &(unm_stats->rx_errors));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_CRC_ERROR_CNT,
+ &(unm_stats->rx_CRC_errors));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
+ &(unm_stats->rx_long_length_error));
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_READ_REG(UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ &(unm_stats->rx_short_length_error));
+
+ /*
+ * For reading rx_MAC_error bit different procedure
+ * UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_TEST_MUX_CTL, 0x15);
+ * UNM_NIC_LOCKED_READ_REG((UNM_CRB_NIU + 0xC0), &temp);
+ * unm_stats->rx_MAC_errors = temp & 0xff;
+ */
+
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK(&adapter->adapter_lock);
+ } else {
+ UNM_SPIN_LOCK_ISR(&adapter->tx_lock);
+ unm_stats->tx_bytes = adapter->stats.txbytes;
+ unm_stats->tx_packets = adapter->stats.xmitedframes +
+ adapter->stats.xmitfinished;
+ unm_stats->rx_bytes = adapter->stats.rxbytes;
+ unm_stats->rx_packets = adapter->stats.no_rcv;
+ unm_stats->rx_errors = adapter->stats.rcvdbadmsg;
+ unm_stats->tx_errors = adapter->stats.nocmddescriptor;
+ unm_stats->rx_short_length_error = adapter->stats.uplcong;
+ unm_stats->rx_long_length_error = adapter->stats.uphcong;
+ unm_stats->rx_CRC_errors = 0;
+ unm_stats->rx_MAC_errors = 0;
+ UNM_SPIN_UNLOCK_ISR(&adapter->tx_lock);
+ }
+ return (0);
+}
+
+int
+unm_nic_fill_statistics_2M(struct unm_adapter_s *adapter,
+ struct unm_statistics *unm_stats)
+{
+ if (adapter->ahw.board_type == UNM_NIC_XGBE) {
+ (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_TX_BYTE_CNT,
+ &(unm_stats->tx_bytes), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_TX_FRAME_CNT,
+ &(unm_stats->tx_packets), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_RX_BYTE_CNT,
+ &(unm_stats->rx_bytes), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_RX_FRAME_CNT,
+ &(unm_stats->rx_packets), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter,
+ UNM_NIU_XGE_AGGR_ERROR_CNT, &(unm_stats->rx_errors), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter, UNM_NIU_XGE_CRC_ERROR_CNT,
+ &(unm_stats->rx_CRC_errors), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter,
+ UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
+ &(unm_stats->rx_long_length_error), 4);
+ (void) unm_nic_hw_read_wx_2M(adapter,
+ UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ &(unm_stats->rx_short_length_error), 4);
+ } else {
+ UNM_SPIN_LOCK_ISR(&adapter->tx_lock);
+ unm_stats->tx_bytes = adapter->stats.txbytes;
+ unm_stats->tx_packets = adapter->stats.xmitedframes +
+ adapter->stats.xmitfinished;
+ unm_stats->rx_bytes = adapter->stats.rxbytes;
+ unm_stats->rx_packets = adapter->stats.no_rcv;
+ unm_stats->rx_errors = adapter->stats.rcvdbadmsg;
+ unm_stats->tx_errors = adapter->stats.nocmddescriptor;
+ unm_stats->rx_short_length_error = adapter->stats.uplcong;
+ unm_stats->rx_long_length_error = adapter->stats.uphcong;
+ unm_stats->rx_CRC_errors = 0;
+ unm_stats->rx_MAC_errors = 0;
+ UNM_SPIN_UNLOCK_ISR(&adapter->tx_lock);
+ }
+ return (0);
+}
+
+int
+unm_nic_clear_statistics_128M(struct unm_adapter_s *adapter)
+{
+ void *addr;
+ int data = 0;
+
+ UNM_WRITE_LOCK(&adapter->adapter_lock);
+ unm_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_TX_BYTE_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_TX_FRAME_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_RX_BYTE_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_RX_FRAME_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_AGGR_ERROR_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_CRC_ERROR_CNT, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_OVERSIZE_FRAME_ERR, &data);
+ /* LINTED: E_FALSE_LOGICAL_EXPR */
+ UNM_NIC_LOCKED_WRITE_REG(UNM_NIU_XGE_UNDERSIZE_FRAME_ERR, &data);
+
+ unm_nic_pci_change_crbwindow_128M(adapter, 1);
+ UNM_WRITE_UNLOCK(&adapter->adapter_lock);
+ unm_nic_clear_stats(adapter);
+ return (0);
+}
+
+int
+unm_nic_clear_statistics_2M(struct unm_adapter_s *adapter)
+{
+ int data = 0;
+
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_TX_BYTE_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_TX_FRAME_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_RX_BYTE_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_RX_FRAME_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_AGGR_ERROR_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_CRC_ERROR_CNT,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_OVERSIZE_FRAME_ERR,
+ &data, 4);
+ (void) unm_nic_hw_write_wx_2M(adapter, UNM_NIU_XGE_UNDERSIZE_FRAME_ERR,
+ &data, 4);
+ unm_nic_clear_stats(adapter);
+ return (0);
+}
+
+/*
+ * unm_nic_ioctl () We provide the tcl/phanmon support
+ * through these ioctls.
+ */
+static void
+unm_nic_ioctl(struct unm_adapter_s *adapter, int cmd, queue_t *q, mblk_t *mp)
+{
+ void *ptr;
+
+ switch (cmd) {
+ case UNM_NIC_CMD:
+ (void) unm_nic_do_ioctl(adapter, q, mp);
+ break;
+
+ case UNM_NIC_NAME:
+ ptr = (void *) mp->b_cont->b_rptr;
+
+ /*
+ * Phanmon checks for "UNM-UNM" string
+ * Replace the hardcoded value with appropriate macro
+ */
+ DPRINTF(-1, (CE_CONT, "UNM_NIC_NAME ioctl executed %d %d\n",
+ cmd, __LINE__));
+ (void) memcpy(ptr, "UNM-UNM", 10);
+ miocack(q, mp, 10, 0);
+ break;
+
+ default:
+ cmn_err(CE_WARN, "Netxen ioctl cmd %x not supported\n", cmd);
+
+ miocnak(q, mp, 0, EINVAL);
+ break;
+ }
+}
+
+int
+unm_nic_resume(unm_adapter *adapter)
+{
+
+ adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
+ (void *) adapter, 50000);
+
+ if (adapter->intr_type == DDI_INTR_TYPE_MSI)
+ (void) ddi_intr_block_enable(&adapter->intr_handle, 1);
+ else
+ (void) ddi_intr_enable(adapter->intr_handle);
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ unm_nic_enable_int(adapter);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+
+ mac_link_update(adapter->mach, LINK_STATE_UP);
+
+ return (DDI_SUCCESS);
+}
+
+int
+unm_nic_suspend(unm_adapter *adapter)
+{
+ mac_link_update(adapter->mach, LINK_STATE_DOWN);
+
+ (void) untimeout(adapter->watchdog_timer);
+
+ UNM_READ_LOCK(&adapter->adapter_lock);
+ unm_nic_disable_int(adapter);
+ UNM_READ_UNLOCK(&adapter->adapter_lock);
+ if (adapter->intr_type == DDI_INTR_TYPE_MSI)
+ (void) ddi_intr_block_disable(&adapter->intr_handle, 1);
+ else
+ (void) ddi_intr_disable(adapter->intr_handle);
+
+ return (DDI_SUCCESS);
+}
+
+static int
+unm_nic_do_ioctl(unm_adapter *adapter, queue_t *wq, mblk_t *mp)
+{
+ unm_nic_ioctl_data_t data;
+ struct unm_nic_ioctl_data *up_data;
+ ddi_acc_handle_t conf_handle;
+ int retval = 0;
+ unsigned int efuse_chip_id;
+ char *ptr1;
+ short *ptr2;
+ int *ptr4;
+
+ up_data = (struct unm_nic_ioctl_data *)(mp->b_cont->b_rptr);
+ (void) memcpy(&data, (void **)(uintptr_t)(mp->b_cont->b_rptr),
+ sizeof (data));
+
+ /* Shouldn't access beyond legal limits of "char u[64];" member */
+ if (data.size > sizeof (data.uabc)) {
+ /* evil user tried to crash the kernel */
+ cmn_err(CE_WARN, "bad size: %d\n", data.size);
+ retval = GLD_BADARG;
+ goto error_out;
+ }
+
+ switch (data.cmd) {
+ case unm_nic_cmd_pci_read:
+
+ if ((retval = adapter->unm_nic_hw_read_ioctl(adapter,
+ data.off, up_data, data.size))) {
+ DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_hw_read_wx "
+ "returned %d\n", __FUNCTION__, __LINE__, retval));
+
+ retval = data.rv;
+ goto error_out;
+ }
+
+ data.rv = 0;
+ break;
+
+ case unm_nic_cmd_pci_write:
+ if ((data.rv = adapter->unm_nic_hw_write_ioctl(adapter,
+ data.off, &(data.uabc), data.size))) {
+ DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_hw_write_wx "
+ "returned %d\n", __FUNCTION__,
+ __LINE__, data.rv));
+ retval = data.rv;
+ goto error_out;
+ }
+ data.size = 0;
+ break;
+
+ case unm_nic_cmd_pci_mem_read:
+ if ((data.rv = adapter->unm_nic_pci_mem_read(adapter,
+ data.off, up_data, data.size))) {
+ DPRINTF(-1, (CE_WARN, "%s(%d) unm_nic_pci_mem_read "
+ "returned %d\n", __FUNCTION__,
+ __LINE__, data.rv));
+ retval = data.rv;
+ goto error_out;
+ }
+ data.rv = 0;
+ break;
+
+ case unm_nic_cmd_pci_mem_write:
+ if ((data.rv = adapter->unm_nic_pci_mem_write(adapter,
+ data.off, &(data.uabc), data.size))) {
+ DPRINTF(-1, (CE_WARN,
+ "%s(%d) unm_nic_cmd_pci_mem_write "
+ "returned %d\n",
+ __FUNCTION__, __LINE__, data.rv));
+ retval = data.rv;
+ goto error_out;
+ }
+
+ data.size = 0;
+ data.rv = 0;
+ break;
+
+ case unm_nic_cmd_pci_config_read:
+
+ if (adapter->pci_cfg_handle != NULL) {
+ conf_handle = adapter->pci_cfg_handle;
+
+ } else if ((retval = pci_config_setup(adapter->dip,
+ &conf_handle)) != DDI_SUCCESS) {
+ DPRINTF(-1, (CE_WARN, "!%s: pci_config_setup failed"
+ " error:%d\n", unm_nic_driver_name, retval));
+ goto error_out;
+
+ } else
+ adapter->pci_cfg_handle = conf_handle;
+
+ switch (data.size) {
+ case 1:
+ ptr1 = (char *)up_data;
+ *ptr1 = (char)pci_config_get8(conf_handle, data.off);
+ break;
+ case 2:
+ ptr2 = (short *)up_data;
+ *ptr2 = (short)pci_config_get16(conf_handle, data.off);
+ break;
+ case 4:
+ ptr4 = (int *)up_data;
+ *ptr4 = (int)pci_config_get32(conf_handle, data.off);
+ break;
+ }
+
+ break;
+
+ case unm_nic_cmd_pci_config_write:
+
+ if (adapter->pci_cfg_handle != NULL) {
+ conf_handle = adapter->pci_cfg_handle;
+ } else if ((retval = pci_config_setup(adapter->dip,
+ &conf_handle)) != DDI_SUCCESS) {
+ DPRINTF(-1, (CE_WARN, "!%s: pci_config_setup failed"
+ " error:%d\n", unm_nic_driver_name, retval));
+ goto error_out;
+ } else {
+ adapter->pci_cfg_handle = conf_handle;
+ }
+
+ switch (data.size) {
+ case 1:
+ pci_config_put8(conf_handle,
+ data.off, *(char *)&(data.uabc));
+ break;
+ case 2:
+ pci_config_put16(conf_handle,
+ data.off, *(short *)(uintptr_t)&(data.uabc));
+ break;
+ case 4:
+ pci_config_put32(conf_handle,
+ data.off, *(u32 *)(uintptr_t)&(data.uabc));
+ break;
+ }
+ data.size = 0;
+ break;
+
+ case unm_nic_cmd_get_stats:
+ data.rv = adapter->unm_nic_fill_statistics(adapter,
+ (struct unm_statistics *)up_data);
+ data.size = sizeof (struct unm_statistics);
+
+ break;
+
+ case unm_nic_cmd_clear_stats:
+ data.rv = adapter->unm_nic_clear_statistics(adapter);
+ break;
+
+ case unm_nic_cmd_get_version:
+ (void) memcpy(up_data, UNM_NIC_VERSIONID,
+ sizeof (UNM_NIC_VERSIONID));
+ data.size = sizeof (UNM_NIC_VERSIONID);
+
+ break;
+
+ case unm_nic_cmd_get_phy_type:
+ cmn_err(CE_WARN, "unm_nic_cmd_get_phy_type unimplemented\n");
+ break;
+
+ case unm_nic_cmd_efuse_chip_id:
+ efuse_chip_id = adapter->unm_nic_pci_read_normalize(adapter,
+ UNM_EFUSE_CHIP_ID);
+ (void) memcpy(up_data, &efuse_chip_id, sizeof (unsigned long));
+ data.rv = 0;
+ break;
+
+ default:
+ cmn_err(CE_WARN, "%s%d: bad command %d\n", adapter->name,
+ adapter->instance, data.cmd);
+ data.rv = GLD_NOTSUPPORTED;
+ data.size = 0;
+ goto error_out;
+ }
+
+work_done:
+ miocack(wq, mp, data.size, data.rv);
+ return (DDI_SUCCESS);
+
+error_out:
+ cmn_err(CE_WARN, "%s(%d) ioctl error\n", __FUNCTION__, data.cmd);
+ miocnak(wq, mp, 0, EINVAL);
+ return (retval);
+}
+
+/*
+ * Local datatype for defining tables of (Offset, Name) pairs
+ */
+typedef struct {
+ offset_t index;
+ char *name;
+} unm_ksindex_t;
+
+static const unm_ksindex_t unm_kstat[] = {
+ { 0, "freehdls" },
+ { 1, "freecmds" },
+ { 2, "tx_bcopy_threshold" },
+ { 3, "rx_bcopy_threshold" },
+ { 4, "xmitcalled" },
+ { 5, "xmitedframes" },
+ { 6, "xmitfinished" },
+ { 7, "txbytes" },
+ { 8, "txcopyed" },
+ { 9, "txmapped" },
+ { 10, "outoftxdmahdl" },
+ { 11, "outofcmddesc" },
+ { 12, "txdropped" },
+ { 13, "polled" },
+ { 14, "uphappy" },
+ { 15, "updropped" },
+ { 16, "csummed" },
+ { 17, "no_rcv" },
+ { 18, "rxbytes" },
+ { 19, "rxcopyed" },
+ { 20, "rxmapped" },
+ { 21, "desballocfailed" },
+ { 22, "outofrxbuf" },
+ { 23, "promiscmode" },
+ { 24, "rxbufshort" },
+ { 25, "allocbfailed" },
+ { -1, NULL }
+};
+
+static int
+unm_kstat_update(kstat_t *ksp, int flag)
+{
+ unm_adapter *adapter;
+ kstat_named_t *knp;
+
+ if (flag != KSTAT_READ)
+ return (EACCES);
+
+ adapter = ksp->ks_private;
+ knp = ksp->ks_data;
+
+ (knp++)->value.ui32 = adapter->freehdls;
+ (knp++)->value.ui64 = adapter->freecmds;
+ (knp++)->value.ui64 = adapter->tx_bcopy_threshold;
+ (knp++)->value.ui64 = adapter->rx_bcopy_threshold;
+
+ (knp++)->value.ui64 = adapter->stats.xmitcalled;
+ (knp++)->value.ui64 = adapter->stats.xmitedframes;
+ (knp++)->value.ui64 = adapter->stats.xmitfinished;
+ (knp++)->value.ui64 = adapter->stats.txbytes;
+ (knp++)->value.ui64 = adapter->stats.txcopyed;
+ (knp++)->value.ui64 = adapter->stats.txmapped;
+ (knp++)->value.ui64 = adapter->stats.outoftxdmahdl;
+ (knp++)->value.ui64 = adapter->stats.outofcmddesc;
+ (knp++)->value.ui64 = adapter->stats.txdropped;
+ (knp++)->value.ui64 = adapter->stats.polled;
+ (knp++)->value.ui64 = adapter->stats.uphappy;
+ (knp++)->value.ui64 = adapter->stats.updropped;
+ (knp++)->value.ui64 = adapter->stats.csummed;
+ (knp++)->value.ui64 = adapter->stats.no_rcv;
+ (knp++)->value.ui64 = adapter->stats.rxbytes;
+ (knp++)->value.ui64 = adapter->stats.rxcopyed;
+ (knp++)->value.ui64 = adapter->stats.rxmapped;
+ (knp++)->value.ui64 = adapter->stats.desballocfailed;
+ (knp++)->value.ui64 = adapter->stats.outofrxbuf;
+ (knp++)->value.ui64 = adapter->stats.promiscmode;
+ (knp++)->value.ui64 = adapter->stats.rxbufshort;
+ (knp++)->value.ui64 = adapter->stats.allocbfailed;
+
+ return (0);
+}
+
+static kstat_t *
+unm_setup_named_kstat(unm_adapter *adapter, int instance, char *name,
+ const unm_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
+{
+ kstat_t *ksp;
+ kstat_named_t *knp;
+ char *np;
+ int type;
+ int count = 0;
+
+ size /= sizeof (unm_ksindex_t);
+ ksp = kstat_create(unm_nic_driver_name, instance, name, "net",
+ KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
+ if (ksp == NULL)
+ return (NULL);
+
+ ksp->ks_private = adapter;
+ ksp->ks_update = update;
+ for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
+ count++;
+ switch (*np) {
+ default:
+ type = KSTAT_DATA_UINT64;
+ break;
+ case '%':
+ np += 1;
+ type = KSTAT_DATA_UINT32;
+ break;
+ case '$':
+ np += 1;
+ type = KSTAT_DATA_STRING;
+ break;
+ case '&':
+ np += 1;
+ type = KSTAT_DATA_CHAR;
+ break;
+ }
+ kstat_named_init(knp, np, type);
+ }
+ kstat_install(ksp);
+
+ return (ksp);
+}
+
+void
+unm_init_kstats(unm_adapter* adapter, int instance)
+{
+ adapter->kstats[0] = unm_setup_named_kstat(adapter,
+ instance, "kstatinfo", unm_kstat,
+ sizeof (unm_kstat), unm_kstat_update);
+}
+
+void
+unm_fini_kstats(unm_adapter* adapter)
+{
+
+ if (adapter->kstats[0] != NULL) {
+ kstat_delete(adapter->kstats[0]);
+ adapter->kstats[0] = NULL;
+ }
+}
+
+static int
+unm_nic_set_pauseparam(unm_adapter *adapter, unm_pauseparam_t *pause)
+{
+ int ret = 0;
+
+ if (adapter->ahw.board_type == UNM_NIC_GBE) {
+ if (unm_niu_gbe_set_rx_flow_ctl(adapter, pause->rx_pause))
+ ret = -EIO;
+
+ if (unm_niu_gbe_set_tx_flow_ctl(adapter, pause->tx_pause))
+ ret = -EIO;
+
+ } else if (adapter->ahw.board_type == UNM_NIC_XGBE) {
+ if (unm_niu_xg_set_tx_flow_ctl(adapter, pause->tx_pause))
+ ret = -EIO;
+ } else
+ ret = -EIO;
+
+ return (ret);
+}
+
+/*
+ *
+ * GLD/MAC interfaces
+ *
+ */
+
+static int
+ntxn_m_start(void *arg)
+{
+ unm_adapter *adapter = arg;
+ int ring;
+
+ UNM_SPIN_LOCK(&adapter->lock);
+ if (adapter->is_up == UNM_ADAPTER_UP_MAGIC) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ return (DDI_SUCCESS);
+ }
+
+ if (init_firmware(adapter) != DDI_SUCCESS) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Failed to init firmware\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ unm_nic_clear_stats(adapter);
+
+ if (unm_nic_hw_resources(adapter) != 0) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Error setting hw resources\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ if (adapter->fw_major < 4) {
+ adapter->crb_addr_cmd_producer =
+ crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer =
+ crb_cmd_consumer[adapter->portnum];
+ unm_nic_update_cmd_producer(adapter, 0);
+ unm_nic_update_cmd_consumer(adapter, 0);
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ if (unm_post_rx_buffers(adapter, ring) != DDI_SUCCESS) {
+ /* TODO: clean up */
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ return (DDI_FAILURE);
+ }
+ }
+
+ if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Could not set mac address\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ if (unm_nic_init_port(adapter) != 0) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Could not initialize port\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ unm_nic_set_link_parameters(adapter);
+
+ /*
+ * P2 and P3 should be handled similarly.
+ */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ if (unm_nic_set_promisc_mode(adapter) != 0) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Could not set promisc mode\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+ } else {
+ nx_p3_nic_set_multi(adapter);
+ }
+ adapter->stats.promiscmode = 1;
+
+ if (unm_nic_set_mtu(adapter, adapter->mtu) != 0) {
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ cmn_err(CE_WARN, "%s%d: Could not set mtu\n",
+ adapter->name, adapter->instance);
+ return (DDI_FAILURE);
+ }
+
+ adapter->watchdog_timer = timeout((void (*)(void *))&unm_watchdog,
+ (void *)adapter, 0);
+
+ adapter->is_up = UNM_ADAPTER_UP_MAGIC;
+
+ if (adapter->intr_type == DDI_INTR_TYPE_MSI)
+ (void) ddi_intr_block_enable(&adapter->intr_handle, 1);
+ else
+ (void) ddi_intr_enable(adapter->intr_handle);
+ unm_nic_enable_int(adapter);
+
+ UNM_SPIN_UNLOCK(&adapter->lock);
+ return (GLD_SUCCESS);
+}
+
+
+/*
+ * This code is kept here for reference so as to
+ * see if something different is required to be done
+ * in GLDV3. This will be deleted later.
+ */
+/* ARGSUSED */
+static void
+ntxn_m_stop(void *arg)
+{
+}
+
+/*ARGSUSED*/
+static int
+ntxn_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
+{
+ /*
+ * When we correctly implement this, invoke nx_p3_nic_set_multi()
+ * or nx_p2_nic_set_multi() here.
+ */
+ return (GLD_SUCCESS);
+}
+
+/*ARGSUSED*/
+static int
+ntxn_m_promisc(void *arg, boolean_t on)
+{
+#if 0
+ int err = 0;
+ struct unm_adapter_s *adapter = arg;
+
+ err = on ? unm_nic_set_promisc_mode(adapter) :
+ unm_nic_unset_promisc_mode(adapter);
+
+ if (err)
+ return (GLD_FAILURE);
+#endif
+
+ return (GLD_SUCCESS);
+}
+
+static int
+ntxn_m_stat(void *arg, uint_t stat, uint64_t *val)
+{
+ struct unm_adapter_s *adapter = arg;
+ struct unm_adapter_stats *portstat = &adapter->stats;
+
+ switch (stat) {
+ case MAC_STAT_IFSPEED:
+ if (adapter->ahw.board_type == UNM_NIC_XGBE) {
+ /* 10 Gigs */
+ *val = 10000000000ULL;
+ } else {
+ /* 1 Gig */
+ *val = 1000000000;
+ }
+ break;
+
+ case MAC_STAT_MULTIRCV:
+ *val = 0;
+ break;
+
+ case MAC_STAT_BRDCSTRCV:
+ case MAC_STAT_BRDCSTXMT:
+ *val = 0;
+ break;
+
+ case MAC_STAT_NORCVBUF:
+ *val = portstat->updropped;
+ break;
+
+ case MAC_STAT_NOXMTBUF:
+ *val = portstat->txdropped;
+ break;
+
+ case MAC_STAT_RBYTES:
+ *val = portstat->rxbytes;
+ break;
+
+ case MAC_STAT_OBYTES:
+ *val = portstat->txbytes;
+ break;
+
+ case MAC_STAT_OPACKETS:
+ *val = portstat->xmitedframes;
+ break;
+
+ case MAC_STAT_IPACKETS:
+ *val = portstat->uphappy;
+ break;
+
+ case MAC_STAT_OERRORS:
+ *val = portstat->xmitcalled - portstat->xmitedframes;
+ break;
+
+ case ETHER_STAT_LINK_DUPLEX:
+ *val = LINK_DUPLEX_FULL;
+ break;
+
+ default:
+ /*
+ * Shouldn't reach here...
+ */
+ *val = 0;
+ DPRINTF(0, (CE_WARN, ": unrecognized parameter = %d, value "
+ "returned 1\n", stat));
+
+ }
+
+ return (0);
+}
+
+static int
+ntxn_m_unicst(void *arg, const uint8_t *mac)
+{
+ struct unm_adapter_s *adapter = arg;
+
+ DPRINTF(-1, (CE_CONT, "%s: called\n", __func__));
+
+ if (unm_nic_macaddr_set(adapter, (uint8_t *)mac))
+ return (EAGAIN);
+ bcopy(mac, adapter->mac_addr, ETHERADDRL);
+
+ return (0);
+}
+
+static mblk_t *
+ntxn_m_tx(void *arg, mblk_t *mp)
+{
+ unm_adapter *adapter = arg;
+ mblk_t *next;
+
+ while (mp != NULL) {
+ next = mp->b_next;
+ mp->b_next = NULL;
+
+ if (unm_nic_xmit_frame(adapter, mp) != B_TRUE) {
+ mp->b_next = next;
+ break;
+ }
+ mp = next;
+ adapter->stats.xmitedframes++;
+ }
+
+ return (mp);
+}
+
+static void
+ntxn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
+{
+ int cmd;
+ struct iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
+ struct unm_adapter_s *adapter = (struct unm_adapter_s *)arg;
+ enum ioc_reply status = IOC_DONE;
+
+ iocp->ioc_error = 0;
+ cmd = iocp->ioc_cmd;
+
+ if (cmd == ND_GET || cmd == ND_SET) {
+ status = unm_nd_ioctl(adapter, wq, mp, iocp);
+ switch (status) {
+ default:
+ case IOC_INVAL:
+ miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
+ EINVAL : iocp->ioc_error);
+ break;
+
+ case IOC_DONE:
+ break;
+
+ case IOC_RESTART_ACK:
+ case IOC_ACK:
+ miocack(wq, mp, 0, 0);
+ break;
+
+ case IOC_RESTART_REPLY:
+ case IOC_REPLY:
+ mp->b_datap->db_type = iocp->ioc_error == 0 ?
+ M_IOCACK : M_IOCNAK;
+ qreply(wq, mp);
+ break;
+ }
+ } else if (cmd <= UNM_NIC_NAME && cmd >= UNM_CMD_START) {
+ unm_nic_ioctl(adapter, cmd, wq, mp);
+ return;
+ } else {
+ miocnak(wq, mp, 0, EINVAL);
+ return;
+ }
+}
+
+/* ARGSUSED */
+static boolean_t
+ntxn_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
+{
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM:
+ {
+ uint32_t *txflags = cap_data;
+
+ *txflags = (HCKSUM_ENABLE |
+ HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM);
+ }
+ break;
+
+ case MAC_CAPAB_POLL:
+ case MAC_CAPAB_MULTIADDRESS:
+ default:
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+#define NETXEN_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
+
+static mac_callbacks_t ntxn_m_callbacks = {
+ NETXEN_M_CALLBACK_FLAGS,
+ ntxn_m_stat,
+ ntxn_m_start,
+ ntxn_m_stop,
+ ntxn_m_promisc,
+ ntxn_m_multicst,
+ ntxn_m_unicst,
+ ntxn_m_tx,
+ NULL, /* mc_resources */
+ ntxn_m_ioctl,
+ ntxn_m_getcapab,
+ NULL, /* mc_open */
+ NULL, /* mc_close */
+ NULL, /* mc_setprop */
+ NULL /* mc_getprop */
+};
+
+int
+unm_register_mac(unm_adapter *adapter)
+{
+ int ret;
+ mac_register_t *macp;
+ unm_pauseparam_t pause;
+
+ dev_info_t *dip = adapter->dip;
+
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
+ cmn_err(CE_WARN, "Memory not available\n");
+ return (DDI_FAILURE);
+ }
+
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = adapter;
+ macp->m_dip = dip;
+ macp->m_instance = adapter->instance;
+ macp->m_src_addr = adapter->mac_addr;
+ macp->m_callbacks = &ntxn_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = adapter->mtu;
+#ifdef SOLARIS11
+ macp->m_margin = VLAN_TAGSZ;
+#endif /* SOLARIS11 */
+
+ ret = mac_register(macp, &adapter->mach);
+ mac_free(macp);
+ if (ret != 0) {
+ cmn_err(CE_WARN, "mac_register failed for port %d\n",
+ adapter->portnum);
+ return (DDI_FAILURE);
+ }
+
+ unm_init_kstats(adapter, adapter->instance);
+
+ /* Register NDD-tweakable parameters */
+ if (unm_nd_init(adapter)) {
+ cmn_err(CE_WARN, "unm_nd_init() failed");
+ return (DDI_FAILURE);
+ }
+
+ pause.rx_pause = adapter->nd_params[PARAM_ADV_PAUSE_CAP].ndp_val;
+ pause.tx_pause = adapter->nd_params[PARAM_ADV_ASYM_PAUSE_CAP].ndp_val;
+
+ if (unm_nic_set_pauseparam(adapter, &pause)) {
+ cmn_err(CE_WARN, "\nBad Pause settings RX %d, Tx %d",
+ pause.rx_pause, pause.tx_pause);
+ }
+ adapter->nd_params[PARAM_PAUSE_CAP].ndp_val = pause.rx_pause;
+ adapter->nd_params[PARAM_ASYM_PAUSE_CAP].ndp_val = pause.tx_pause;
+
+ return (DDI_SUCCESS);
+}
diff --git a/usr/src/uts/common/io/ntxn/unm_version.h b/usr/src/uts/common/io/ntxn/unm_version.h
new file mode 100644
index 0000000000..b0648f36b4
--- /dev/null
+++ b/usr/src/uts/common/io/ntxn/unm_version.h
@@ -0,0 +1,31 @@
+/*
+ * 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 2008 NetXen, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _UNM_VERSION_H
+#define _UNM_VERSION_H
+#define UNM_NIC_VERSIONID "4.0.219"
+#define _UNM_NIC_MAJOR 4
+#define _UNM_NIC_MINOR 0
+#define _UNM_NIC_SUBVERSION 219
+#endif /* !_UNM_VERSION_H */
diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared
index b87b3bf7c0..8608fcf00d 100644
--- a/usr/src/uts/intel/Makefile.intel.shared
+++ b/usr/src/uts/intel/Makefile.intel.shared
@@ -203,6 +203,7 @@ DRV_KMODS += bofi
DRV_KMODS += bscbus
DRV_KMODS += bscv
DRV_KMODS += chxge
+DRV_KMODS += ntxn
DRV_KMODS += clone
DRV_KMODS += cmdk
DRV_KMODS += cn
diff --git a/usr/src/uts/intel/ntxn/Makefile b/usr/src/uts/intel/ntxn/Makefile
new file mode 100644
index 0000000000..f33fa58f1e
--- /dev/null
+++ b/usr/src/uts/intel/ntxn/Makefile
@@ -0,0 +1,95 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# This makefile drives the production of the Neterion Xframe
+# 10G Ethernet (XGE) driver module in x86 systems
+#
+
+#
+# Paths to the base of the uts directory trees
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = ntxn
+OBJECTS = $(NTXN_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(NTXN_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)
+
+
+CFLAGS += -DSOLARIS11 -xO4
+CFLAGS64 += -DSOLARIS11 -xO -I./
+
+#
+# Driver depends on MAC & IP
+#
+LDFLAGS += -dy -N misc/mac -N drv/ip
+
+# Lint flag
+#
+LINTFLAGS += $(NTXN_DFLAGS) $(NTXN_KFLAGS)
+LINTFLAGS += -DSOLARIS11
+
+#
+#
+# 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