# HG changeset patch # User lucy wang - Sun Microsystems - Beijing China # Date 1225159573 -28800 # Node ID 59ff93e4da95d625af4b2466e0c64db56c02fc4b # Parent 47745077dc336df6903190995d700691c53450a0 PSARC 2008/045 NetXen 10 Gigabit Ethernet Driver 6472698 NetXen 1Gb/10Gb nic driver diff -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/Makefile --- a/usr/src/pkgdefs/Makefile Tue Oct 28 09:59:16 2008 +0800 +++ b/usr/src/pkgdefs/Makefile Tue Oct 28 10:06:13 2008 +0800 @@ -157,7 +157,8 @@ SUNWxsvc \ SUNWxvmipar \ SUNWxvmipau \ - SUNWxvmpv + SUNWxvmpv \ + SUNWntxn i386_XMODS= \ BRCMbnx \ diff -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/Makefile Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/pkginfo.tmpl Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/postinstall --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/postinstall Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/postremove --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/postremove Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/prototype_com --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/prototype_com Tue Oct 28 10:06:13 2008 +0800 @@ -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 # where to find pkg objects +#!include # include another 'prototype' file +#!default # default used if not specified on entry +#!= # 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/pkgdefs/SUNWntxn/prototype_i386 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWntxn/prototype_i386 Tue Oct 28 10:06:13 2008 +0800 @@ -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 # where to find pkg objects +#!include # include another 'prototype' file +#!default # default used if not specified on entry +#!= # 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/tools/opensolaris/license-list --- a/usr/src/tools/opensolaris/license-list Tue Oct 28 09:59:16 2008 +0800 +++ b/usr/src/tools/opensolaris/license-list Tue Oct 28 10:06:13 2008 +0800 @@ -166,3 +166,4 @@ 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/Makefile.files --- a/usr/src/uts/common/Makefile.files Tue Oct 28 09:59:16 2008 +0800 +++ b/usr/src/uts/common/Makefile.files Tue Oct 28 10:06:13 2008 +0800 @@ -1780,3 +1780,9 @@ 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/Makefile.rules --- a/usr/src/uts/common/Makefile.rules Tue Oct 28 09:59:16 2008 +0800 +++ b/usr/src/uts/common/Makefile.rules Tue Oct 28 10:06:13 2008 +0800 @@ -1017,6 +1017,10 @@ $(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/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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE Tue Oct 28 10:06:13 2008 +0800 @@ -0,0 +1,4 @@ +/* + * Copyright 2008 NetXen, Inc. All rights reserved. + * Use is subject to license terms. + */ diff -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/THIRDPARTYLICENSE.descrip Tue Oct 28 10:06:13 2008 +0800 @@ -0,0 +1,1 @@ +ntxn - 10Gb/1Gb NIC driver for NetXen's Ethernet cards diff -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/driver_info.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/driver_info.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/message.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/message.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/nic_cmn.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/nic_cmn.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/nic_phan_reg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/nic_phan_reg.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/niu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/niu.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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, + ®, 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, + ®, 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*)®, 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, ®, 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), ®, 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, ®, 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, ®, 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, ®, 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, ®, 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), + ®, 4); + reg.rx_flowctl = enable; + adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port), + ®, 4); + + return (0); +} diff -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/nx_errorcode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/nx_errorcode.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/nx_hw_pci_regs.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/nxhal_nic_interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/nxhal_nic_interface.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_brdcfg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_brdcfg.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_gem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_gem.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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", ®_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, ®size); + 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, ®_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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_inc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_inc.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_ndd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_ndd.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 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 field terminates the array. + * + * The 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 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 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= ". + * 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_ctx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_ctx.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_hw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_hw.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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), ®, 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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_hw.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_hw.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_init.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_ioctl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_ioctl.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_isr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_isr.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_nic_main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_nic_main.c Tue Oct 28 10:06:13 2008 +0800 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/common/io/ntxn/unm_version.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/ntxn/unm_version.h Tue Oct 28 10:06:13 2008 +0800 @@ -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 -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/intel/Makefile.intel.shared --- a/usr/src/uts/intel/Makefile.intel.shared Tue Oct 28 09:59:16 2008 +0800 +++ b/usr/src/uts/intel/Makefile.intel.shared Tue Oct 28 10:06:13 2008 +0800 @@ -203,6 +203,7 @@ DRV_KMODS += bscbus DRV_KMODS += bscv DRV_KMODS += chxge +DRV_KMODS += ntxn DRV_KMODS += clone DRV_KMODS += cmdk DRV_KMODS += cn diff -r 47745077dc33 -r 59ff93e4da95 usr/src/uts/intel/ntxn/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/ntxn/Makefile Tue Oct 28 10:06:13 2008 +0800 @@ -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