summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/Makefile.master7
-rw-r--r--usr/src/cmd/cmd-crypto/etc/Makefile13
-rw-r--r--usr/src/cmd/cmd-crypto/etc/certs/SUNWCryptographic11_Limited49
-rw-r--r--usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.c31
-rw-r--r--usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.h18
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile2
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.c489
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.h126
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/ontario/common/ontario.c23
-rw-r--r--usr/src/pkgdefs/Makefile5
-rw-r--r--usr/src/pkgdefs/SUNWcakr.v/prototype_com9
-rw-r--r--usr/src/pkgdefs/SUNWcart200.v/prototype_com2
-rw-r--r--usr/src/pkgdefs/SUNWcryptoint/postinstall10
-rw-r--r--usr/src/pkgdefs/SUNWcryptoint/preremove8
-rw-r--r--usr/src/pkgdefs/SUNWcryptoint/prototype_com8
-rw-r--r--usr/src/pkgdefs/SUNWcsr/prototype_com1
-rw-r--r--usr/src/pkgdefs/SUNWkvmt200.v/prototype_com8
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/Makefile38
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/pkginfo.tmpl59
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/postinstall117
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/preremove105
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/prototype_com55
-rw-r--r--usr/src/pkgdefs/SUNWn2cp.v/prototype_sparc48
-rw-r--r--usr/src/pkgdefs/SUNWn2cpact.v/Makefile36
-rw-r--r--usr/src/pkgdefs/SUNWn2cpact.v/depend45
-rw-r--r--usr/src/pkgdefs/SUNWn2cpact.v/pkginfo.tmpl59
-rw-r--r--usr/src/pkgdefs/SUNWn2cpact.v/prototype_com52
-rw-r--r--usr/src/pkgdefs/SUNWn2cpact.v/prototype_sparc48
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/Makefile38
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/pkginfo.tmpl48
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/postinstall132
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/postremove38
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/prototype_com48
-rw-r--r--usr/src/pkgdefs/SUNWniumx.v/prototype_sparc57
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/Makefile38
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/pkginfo.tmpl49
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/postinstall132
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/postremove38
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/prototype_com47
-rw-r--r--usr/src/pkgdefs/SUNWnxge.v/prototype_sparc57
-rw-r--r--usr/src/pkgdefs/SUNWust2.v/Makefile38
-rw-r--r--usr/src/pkgdefs/SUNWust2.v/pkginfo.tmpl55
-rw-r--r--usr/src/pkgdefs/SUNWust2.v/prototype_com55
-rw-r--r--usr/src/pkgdefs/SUNWust2.v/prototype_sparc48
-rw-r--r--usr/src/req.flg2
-rw-r--r--usr/src/tools/findunref/exception_list3
-rw-r--r--usr/src/uts/Makefile.targ6
-rw-r--r--usr/src/uts/Makefile.uts7
-rw-r--r--usr/src/uts/common/io/pcie.c66
-rw-r--r--usr/src/uts/common/os/kcpc.c15
-rw-r--r--usr/src/uts/common/sys/pci_impl.h23
-rw-r--r--usr/src/uts/common/sys/pcie_impl.h1
-rw-r--r--usr/src/uts/common/sys/sha1.h6
-rw-r--r--usr/src/uts/sparc/os/driver_aliases3
-rw-r--r--usr/src/uts/sparc/os/name_to_major1
-rw-r--r--usr/src/uts/sun4/io/px/px_dma.c20
-rw-r--r--usr/src/uts/sun4/io/px/px_dma.h1
-rw-r--r--usr/src/uts/sun4/io/px/px_fdvma.c6
-rw-r--r--usr/src/uts/sun4/io/px/px_ioapi.h48
-rw-r--r--usr/src/uts/sun4/io/px/px_mmu.c10
-rw-r--r--usr/src/uts/sun4/io/px/px_obj.h1
-rw-r--r--usr/src/uts/sun4/io/px/px_pci.c60
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_pci.c48
-rw-r--r--usr/src/uts/sun4v/Makefile.files25
-rw-r--r--usr/src/uts/sun4v/Makefile.rules27
-rw-r--r--usr/src/uts/sun4v/Makefile.sun4v.shared9
-rw-r--r--usr/src/uts/sun4v/Makefile.workarounds6
-rw-r--r--usr/src/uts/sun4v/cpu/common_asm.s17
-rw-r--r--usr/src/uts/sun4v/cpu/niagara2.c232
-rw-r--r--usr/src/uts/sun4v/cpu/niagara2_asm.s144
-rw-r--r--usr/src/uts/sun4v/cpu/niagara_perfctr.c20
-rw-r--r--usr/src/uts/sun4v/io/niumx/niumx.c965
-rw-r--r--usr/src/uts/sun4v/io/niumx/niumx_var.h151
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi.c107
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi.h247
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_espc.c355
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_espc.h87
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_fflp.c2976
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_fflp.h1187
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_ipp.c686
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_ipp.h188
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_mac.c3765
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_mac.h573
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.c2347
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.h1335
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_txc.c1144
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_txc.h138
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_txdma.c2057
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_txdma.h290
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_vir.c1504
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_vir.h690
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_zcp.c758
-rw-r--r--usr/src/uts/sun4v/io/nxge/npi/npi_zcp.h187
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_classify.c208
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_espc.c218
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_fflp.c2261
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_fflp_hash.c404
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_fm.c856
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_fzc.c1039
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_hcall.s114
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_hw.c1047
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_ipp.c606
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_kstats.c2781
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_mac.c3383
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_main.c4226
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_ndd.c2840
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_rxdma.c4873
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_send.c1037
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_txc.c420
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_txdma.c3268
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_virtual.c4135
-rw-r--r--usr/src/uts/sun4v/io/nxge/nxge_zcp.c458
-rw-r--r--usr/src/uts/sun4v/io/px/px_lib4v.c49
-rw-r--r--usr/src/uts/sun4v/io/px/px_lib4v.h5
-rw-r--r--usr/src/uts/sun4v/io/vnex.c3
-rw-r--r--usr/src/uts/sun4v/ml/trap_table.s6
-rw-r--r--usr/src/uts/sun4v/niagara2/Makefile108
-rw-r--r--usr/src/uts/sun4v/niagara2_pcbe/Makefile77
-rw-r--r--usr/src/uts/sun4v/niumx/Makefile104
-rw-r--r--usr/src/uts/sun4v/nxge/Makefile140
-rw-r--r--usr/src/uts/sun4v/ontario/Makefile2
-rw-r--r--usr/src/uts/sun4v/os/error.c71
-rw-r--r--usr/src/uts/sun4v/os/mach_startup.c55
-rw-r--r--usr/src/uts/sun4v/pcbe/niagara2_pcbe.c582
-rw-r--r--usr/src/uts/sun4v/sys/Makefile28
-rw-r--r--usr/src/uts/sun4v/sys/error.h14
-rw-r--r--usr/src/uts/sun4v/sys/hsvc.h3
-rw-r--r--usr/src/uts/sun4v/sys/n2cp.h702
-rw-r--r--usr/src/uts/sun4v/sys/n2rng.h278
-rw-r--r--usr/src/uts/sun4v/sys/ncp.h45
-rw-r--r--usr/src/uts/sun4v/sys/ncs.h100
-rw-r--r--usr/src/uts/sun4v/sys/niagara2regs.h124
-rw-r--r--usr/src/uts/sun4v/sys/niagaraasi.h13
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge.h1154
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_common.h483
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_common_impl.h1035
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_defs.h465
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_espc.h236
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_espc_hw.h64
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_fflp.h233
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_fflp_hash.h58
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_fflp_hw.h1668
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_flow.h198
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_fm.h247
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_fzc.h93
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_hw.h1057
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_impl.h857
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_ipp.h83
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_ipp_hw.h251
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_mac.h239
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_mac_hw.h2408
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_mii.h454
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_n2_esr_hw.h363
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_phy_hw.h633
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_rxdma.h462
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_rxdma_hw.h1899
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_sr_hw.h793
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_str_cfg.h75
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_txc.h83
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_txc_hw.h1270
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_txdma.h304
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_txdma_hw.h1031
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_virtual.h80
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_zcp.h75
-rw-r--r--usr/src/uts/sun4v/sys/nxge/nxge_zcp_hw.h771
-rw-r--r--usr/src/uts/sun4v/vm/mach_sfmmu.c2
166 files changed, 80503 insertions, 237 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index c76e5c357e..e43a36e3b7 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -775,6 +775,10 @@ $(EXPORT_RELEASE_BUILD)ELFSIGN_KEY = \
$(CLOSED)/cmd/cmd-crypto/etc/keys/SUNWosnet
$(EXPORT_RELEASE_BUILD)ELFSIGN_CERT= \
$(CLOSED)/cmd/cmd-crypto/etc/certs/SUNWosnet
+$(EXPORT_RELEASE_BUILD)ELFSIGN_KEY_LIMITED = \
+ $(CLOSED)/cmd/cmd-crypto/etc/keys/SUNWosnetLimited
+$(EXPORT_RELEASE_BUILD)ELFSIGN_CERT_LIMITED= \
+ $(CLOSED)/cmd/cmd-crypto/etc/certs/SUNWosnetLimited
$(EXPORT_RELEASE_BUILD)ELFSIGN_SEKEY = \
$(CLOSED)/cmd/cmd-crypto/etc/keys/SUNWosnetSolaris
$(EXPORT_RELEASE_BUILD)ELFSIGN_SECERT= \
@@ -782,6 +786,9 @@ $(EXPORT_RELEASE_BUILD)ELFSIGN_SECERT= \
$(EXPORT_RELEASE_BUILD)ELFSIGN_CRYPTO= $(ELFSIGN_O) sign \
$(ELFSIGN_FORMAT_OPTION) \
-k $(ELFSIGN_KEY) -c $(ELFSIGN_CERT) -e $@
+$(EXPORT_RELEASE_BUILD)ELFSIGN_CRYPTO_LIMITED= $(ELFSIGN_O) sign \
+ $(ELFSIGN_FORMAT_OPTION) \
+ -k $(ELFSIGN_KEY_LIMITED) -c $(ELFSIGN_CERT_LIMITED) -e $@
$(EXPORT_RELEASE_BUILD)ELFSIGN_OBJECT= $(ELFSIGN_O) sign \
$(ELFSIGN_FORMAT_OPTION) \
-k $(ELFSIGN_SEKEY) -c $(ELFSIGN_SECERT) -e $@
diff --git a/usr/src/cmd/cmd-crypto/etc/Makefile b/usr/src/cmd/cmd-crypto/etc/Makefile
index 76cdfbd320..248016817c 100644
--- a/usr/src/cmd/cmd-crypto/etc/Makefile
+++ b/usr/src/cmd/cmd-crypto/etc/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,18 +19,20 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
RELEASECERTS = SUNW_SunOS_5.10
+RELEASECRYPTO = SUNW_SunOS_5.10 \
+ SUNW_SunOS_5.11_Limited
ETCCRYPTOFILES = \
kcf.conf \
pkcs11.conf \
- $(RELEASECERTS:%=certs/%) \
+ $(RELEASECRYPTO:%=certs/%) \
certs/CA
ETCCERTSFILES = \
@@ -57,7 +58,7 @@ IETCCERTSFILES= $(ETCCERTSFILES:%=$(ROOTETCCERTSDIR)/%)
$(ROOTCRYPTODIR)/%: %
$(INS.file)
-$(RELEASECERTS:%=$(ROOTCRYPTODIR)/certs/%): \
+$(RELEASECRYPTO:%=$(ROOTCRYPTODIR)/certs/%): \
certs/$(@F:SUNW_SunOS_5.%=SUNWCryptographic%)
$(RM) $@
$(INS) -s -m $(FILEMODE) -f $(@D) \
diff --git a/usr/src/cmd/cmd-crypto/etc/certs/SUNWCryptographic11_Limited b/usr/src/cmd/cmd-crypto/etc/certs/SUNWCryptographic11_Limited
new file mode 100644
index 0000000000..4d960f7c1a
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/etc/certs/SUNWCryptographic11_Limited
@@ -0,0 +1,49 @@
+ Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+
+
+ident "%Z%%M% %I% %E% SMI"
+
+-----BEGIN CERTIFICATE-----
+MIID+DCCAuCgAwIBAgIEFAAAJDANBgkqhkiG9w0BAQUFADBMMR0wGwYDVQQKExRT
+dW4gTWljcm9zeXN0ZW1zIEluYzErMCkGA1UEAxMiU29sYXJpcyBDcnlwdG9ncmFw
+aGljIEZyYW1ld29yayBDQTAeFw0wNjAxMTcyMTUzMzhaFw0xMjA1MjYyMDUzMzha
+MHUxEzARBgNVBAMTClN1bk9TIDUuMTExFTATBgNVBAsTDFVzYWdlTGltaXRlZDEo
+MCYGA1UECxMfU29sYXJpcyBDcnlwdG9ncmFwaGljIEZyYW1ld29yazEdMBsGA1UE
+ChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJFtVRdwryKcSX5lqz6aAbmNy9RbHhy1KF+F6ddDAMTJcZMlg8AynhMLhtVe
+LBNKpTnJ4B/Nb8mNRYl4L6ajoVG1G5F0YA5TKVEjUGUaEIz3cup1sG7ljNTs+lWb
+8O7M+19kZCrsxM2sbvzJx60JhmjjpKxPy8FP/hJ+cFYqbqeZAgMBAAGjggE7MIIB
+NzAdBgNVHQ4EFgQUqy6nnhlVDZg5ftV6j/lR8Z1qiCwwHwYDVR0jBBgwFoAUQghO
+JN0Okzm+CUHvKd4bEFFPLMcwDgYDVR0PAQH/BAQDAgeAMEcGA1UdIARAMD4wPAYL
+YIZIAYb3AIN9k18wLTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5zdW4uY29tL3Br
+aS9jcHMuaHRtbDCBhgYDVR0fBH8wfTB7oCegJYYjaHR0cDovL3d3dy5zdW4uY29t
+L3BraS9wa2lzY2ZjYS5jcmyiUKROMEwxKzApBgNVBAMTIlNvbGFyaXMgQ3J5cHRv
+Z3JhcGhpYyBGcmFtZXdvcmsgQ0ExHTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMg
+SW5jMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4IBAQAkIzct
+iqdNTMVBLh8xh4Mvqw8tVM9y2tVksxLzK/Clbtu0QyaRNylc2+B0ScPkKwKs9GDT
+oLzZmcx+hOmmxA4UDUsKrbTdncVoX6qdwSDvHbwu5vndfwAcItULJt+pHz10UCFB
+3fGbZe3ZUu0hzViD2NF2uRWcpCIFKCfTESbQ16IOCoCWOSK0QJdkSU2bwe5r7pBl
+HznAEkX8XRI25cXCzg6wSS2dAJ9Lk5SS3LswWZt1M0FDUQfb8LjAq4nuJ58sKmNI
+HEUxf8QGrcXNiRqJP8v5lQGxnBes6Y9g7ASjzTCpFr+xefjCY0HqckDghbcd1XA2
+yzJtabW9y96Rf251
+-----END CERTIFICATE-----
diff --git a/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.c b/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.c
index c4c384a08e..286c571049 100644
--- a/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.c
+++ b/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -265,21 +264,17 @@ piclsbl_handler(const char *ename, const void *earg, size_t size,
}
}
- if (strcmp(hdd_location, HDD0) == 0) {
- req_ptr->sbl_id = PCP_SBL_HDD0;
- target = 0;
- } else if (strcmp(hdd_location, HDD1) == 0) {
- req_ptr->sbl_id = PCP_SBL_HDD1;
- target = 1;
- } else if (strcmp(hdd_location, HDD2) == 0) {
- req_ptr->sbl_id = PCP_SBL_HDD2;
- target = 2;
- } else if (strcmp(hdd_location, HDD3) == 0) {
- req_ptr->sbl_id = PCP_SBL_HDD3;
- target = 3;
+ /*
+ * Strip off the target from the NAC name.
+ * The disk NAC will always be HDD#
+ */
+ if (strncmp(hdd_location, NAC_DISK_PREFIX,
+ strlen(NAC_DISK_PREFIX)) == 0) {
+ (void) sscanf(hdd_location, "%*3s%d", &req_ptr->sbl_id);
+ target = (int)req_ptr->sbl_id;
} else {
- /* this is not one of the onboard disks */
- goto sbl_return;
+ /* this is not one of the onboard disks */
+ goto sbl_return;
}
/*
diff --git a/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.h b/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.h
index edac740535..e9e687e12a 100644
--- a/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.h
+++ b/usr/src/cmd/picl/plugins/sun4v/ontario/piclsbl/piclsbl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,10 +50,7 @@ typedef struct disk_lookup {
#define PCPINIT_TIMEOUT 0x05
#define PCPCOMM_TIMEOUT 0x10
-#define HDD0 "HDD0"
-#define HDD1 "HDD1"
-#define HDD2 "HDD2"
-#define HDD3 "HDD3"
+#define NAC_DISK_PREFIX "HDD"
/* message types */
#define PCP_SBL_CONTROL 0x3
@@ -66,12 +62,6 @@ typedef struct pcp_sbl_req {
uint32_t sbl_action;
} pcp_sbl_req_t;
-/* sbl_id */
-#define PCP_SBL_HDD0 0x0
-#define PCP_SBL_HDD1 0x1
-#define PCP_SBL_HDD2 0x2
-#define PCP_SBL_HDD3 0x3
-
/* sbl_action */
#define PCP_SBL_ENABLE 0x1
#define PCP_SBL_DISABLE 0x2
diff --git a/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile b/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
index 41af200087..384b8c4f3f 100644
--- a/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
+++ b/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
@@ -28,7 +28,7 @@
UTSBASE = ../../../../uts
-PLATFORM_OBJECTS= ontario.o erie.o pelton.o stpaul.o
+PLATFORM_OBJECTS= ontario.o erie.o pelton.o stpaul.o huron.o
include ../Makefile.com
diff --git a/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.c b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.c
new file mode 100644
index 0000000000..ef2940adfc
--- /dev/null
+++ b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.c
@@ -0,0 +1,489 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Sun4v Platform specific functions.
+ *
+ * called when :
+ * machine_type == huron
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <kstat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <libintl.h>
+#include <note.h>
+#include <sys/systeminfo.h>
+#include <sys/openpromio.h>
+#include <sys/sysmacros.h>
+#include <picl.h>
+#include "picldefs.h"
+#include <pdevinfo.h>
+#include <display.h>
+#include <display_sun4v.h>
+#include <libprtdiag.h>
+#include "huron.h"
+
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+
+static void
+huron_get_bus_type(char *path, struct io_card *card)
+{
+ if ((strcmp(path, HURON_N2_XAUI0) == 0) ||
+ (strcmp(path, HURON_N2_XAUI1) == 0)) {
+ (void) strcpy(card->bus_type, "SIU");
+ } else {
+ (void) strcpy(card->bus_type, "PCIE");
+ }
+}
+
+void
+huron_get_slot_number(char *path, struct io_card *card)
+{
+ if (strcmp(path, HURON_N2_XAUI0) == 0) {
+ (void) strcpy(card->slot_str, "0");
+ card->slot = 0;
+ } else if (strcmp(path, HURON_N2_XAUI1) == 0) {
+ (void) strcpy(card->slot_str, "1");
+ card->slot = 1;
+ } else if (strncmp(path, HURON_PCIE_SLOT1,
+ strlen(HURON_PCIE_SLOT1)) == 0) {
+ (void) strcpy(card->slot_str, "1");
+ card->slot = 1;
+ } else if (strncmp(path, HURON_PCIE_SLOT2,
+ strlen(HURON_PCIE_SLOT2)) == 0) {
+ (void) strcpy(card->slot_str, "2");
+ card->slot = 2;
+ } else if (strncmp(path, HURON_PCIE_SLOT3,
+ strlen(HURON_PCIE_SLOT3)) == 0) {
+ (void) strcpy(card->slot_str, "3");
+ card->slot = 3;
+ } else if (strncmp(path, HURON_PCIE_SLOT4,
+ strlen(HURON_PCIE_SLOT4)) == 0) {
+ (void) strcpy(card->slot_str, "4");
+ card->slot = 4;
+ } else if (strncmp(path, HURON_PCIE_SLOT5,
+ strlen(HURON_PCIE_SLOT5)) == 0) {
+ (void) strcpy(card->slot_str, "5");
+ card->slot = 5;
+ } else if (strncmp(path, HURON_PCIE_SLOT6,
+ strlen(HURON_PCIE_SLOT6)) == 0) {
+ (void) strcpy(card->slot_str, "6");
+ card->slot = 6;
+ } else {
+ (void) strcpy(card->slot_str, MOTHERBOARD);
+ card->slot = NO_SLOT;
+ }
+}
+
+int
+huron_get_network_instance(char *path)
+{
+ if (strcmp(path, HURON_NETWORK_0) == 0) {
+ return (0);
+ } else if (strcmp(path, HURON_NETWORK_1) == 0) {
+ return (1);
+ } else if (strcmp(path, HURON_NETWORK_2) == 0) {
+ return (2);
+ } else if (strcmp(path, HURON_NETWORK_3) == 0) {
+ return (3);
+ } else if (strcmp(path, HURON_N2_XAUI0) == 0) {
+ return (0);
+ } else if (strcmp(path, HURON_N2_XAUI1) == 0) {
+ return (1);
+ } else {
+ return (-1);
+ }
+}
+/*
+ * add all io devices under pci in io list
+ */
+/* ARGSUSED */
+int
+huron_pci_callback(picl_nodehdl_t pcih, void *args)
+{
+ int err = PICL_SUCCESS;
+ picl_nodehdl_t nodeh;
+ char path[MAXSTRLEN];
+ char parent_path[MAXSTRLEN];
+ char piclclass[PICL_CLASSNAMELEN_MAX];
+ char name[MAXSTRLEN];
+ char model[MAXSTRLEN];
+ char *compatible;
+ char binding_name[MAXSTRLEN];
+ struct io_card pci_card;
+ int32_t instance;
+
+ err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path,
+ sizeof (parent_path));
+ if (err != PICL_SUCCESS) {
+ return (err);
+ }
+
+ /* Walk through the children */
+
+ err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
+ sizeof (picl_nodehdl_t));
+
+ while (err == PICL_SUCCESS) {
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
+ piclclass, sizeof (piclclass));
+ if (err != PICL_SUCCESS)
+ return (err);
+
+ if (strcmp(piclclass, "pciex") == 0) {
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
+ &nodeh, sizeof (picl_nodehdl_t));
+ continue;
+ }
+
+ if (strcmp(piclclass, "siu") == 0) {
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
+ &nodeh, sizeof (picl_nodehdl_t));
+ continue;
+ }
+
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
+ path, sizeof (path));
+ if (err != PICL_SUCCESS) {
+ return (err);
+ }
+
+ (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
+
+ huron_get_bus_type(parent_path, &pci_card);
+
+ huron_get_slot_number(parent_path, &pci_card);
+
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, &name,
+ sizeof (name));
+ if (err == PICL_PROPNOTFOUND)
+ (void) strcpy(name, "");
+ else if (err != PICL_SUCCESS)
+ return (err);
+
+
+ /* Figure NAC name */
+ if ((strcmp(name, NETWORK) == 0) &&
+ (strcmp(pci_card.slot_str, MOTHERBOARD) == 0)) {
+ instance = huron_get_network_instance(path);
+ (void) snprintf(pci_card.status,
+ sizeof (pci_card.status), "%s/%s%d", MOTHERBOARD,
+ "NET", instance);
+ } else {
+ if (pci_card.slot != NO_SLOT) {
+ (void) snprintf(pci_card.status,
+ sizeof (pci_card.status), "%s/%s%d",
+ MOTHERBOARD, pci_card.bus_type,
+ pci_card.slot);
+ } else {
+ (void) snprintf(pci_card.status,
+ sizeof (pci_card.status), "%s/%s",
+ MOTHERBOARD, pci_card.bus_type);
+ }
+ }
+
+ /*
+ * Get the name of this card. Iif binding_name is found,
+ * name will be <nodename>-<binding_name>
+ */
+
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
+ &binding_name, sizeof (binding_name));
+ if (err == PICL_PROPNOTFOUND) {
+ /*
+ * if compatible prop is found, name will be
+ * <nodename>-<compatible>
+ */
+ err = huron_get_first_compatible_value(nodeh,
+ &compatible);
+ if (err == PICL_SUCCESS) {
+ (void) strlcat(name, "-", MAXSTRLEN);
+ (void) strlcat(name, compatible, MAXSTRLEN);
+ free(compatible);
+ } else if (err != PICL_PROPNOTFOUND) {
+ return (err);
+ }
+ } else if (err != PICL_SUCCESS) {
+ return (err);
+ } else if (strcmp(name, binding_name) != 0) {
+ (void) strlcat(name, "-", MAXSTRLEN);
+ (void) strlcat(name, binding_name, MAXSTRLEN);
+ }
+
+ (void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
+
+ /* Get the model of this card */
+
+ err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
+ &model, sizeof (model));
+ if (err == PICL_PROPNOTFOUND)
+ (void) strcpy(model, "");
+ else if (err != PICL_SUCCESS)
+ return (err);
+ (void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
+
+ /* Print NAC name */
+ log_printf("%-11s", pci_card.status);
+ /* Print IO Type */
+ log_printf("%6s", pci_card.bus_type);
+ /* Print Slot # */
+ log_printf("%5s", pci_card.slot_str);
+ /* Print Parent Path */
+ log_printf("%46.45s", pci_card.notes);
+ /* Printf Card Name */
+ if (strlen(pci_card.name) > 24)
+ log_printf("%25.24s+", pci_card.name);
+ else
+ log_printf("%26s", pci_card.name);
+ /* Print Card Model */
+ if (strlen(pci_card.model) > 10)
+ log_printf("%10.9s+", pci_card.model);
+ else
+ log_printf("%10s", pci_card.model);
+ log_printf("\n");
+
+ err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
+ sizeof (picl_nodehdl_t));
+
+ }
+
+ return (PICL_WALK_CONTINUE);
+}
+
+/*
+ * local functions
+ */
+/*
+ * add all io devices under pci in io list
+ */
+/* ARGSUSED */
+int
+huron_hw_rev_callback(picl_nodehdl_t pcih, void *args)
+{
+ int err = PICL_SUCCESS;
+ char path[MAXSTRLEN] = "";
+ char device_path[MAXSTRLEN];
+ char NAC[MAXSTRLEN];
+ char *compatible;
+ int32_t revision;
+ int device_found = 0;
+
+ err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, path,
+ sizeof (path));
+ if (err != PICL_SUCCESS) {
+ return (err);
+ }
+
+ if ((strcmp(path, HURON_NETWORK_0) == 0) ||
+ (strcmp(path, HURON_NETWORK_1) == 0)) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s%d",
+ MOTHERBOARD, OPHIR, 0);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+
+ if ((strcmp(path, HURON_NETWORK_2) == 0) ||
+ (strcmp(path, HURON_NETWORK_3) == 0)) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", MOTHERBOARD,
+ OPHIR, 1);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+
+ if (strcmp(path, HURON_SWITCH_A_PATH) == 0) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s",
+ MOTHERBOARD, HURON_SWITCH_A);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+
+ if (strcmp(path, HURON_SWITCH_B_PATH) == 0) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
+ HURON_SWITCH_B);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+
+ if (strcmp(path, HURON_SWITCH_C_PATH) == 0) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
+ HURON_SWITCH_C);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+
+ if (strcmp(path, HURON_LSI_PATH) == 0) {
+ device_found = 1;
+ (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD,
+ SAS_SATA_HBA);
+ revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID,
+ &err);
+ }
+ if (device_found == 1) {
+ (void) strcpy(device_path, path);
+ err = huron_get_first_compatible_value(pcih, &compatible);
+
+ /* Print NAC name */
+ log_printf("%-20s", NAC);
+ /* Print Device Path */
+ if (strlen(device_path) > 45)
+ log_printf("%45.44s+", device_path);
+ else
+ log_printf("%46s", device_path);
+ /* Print Compatible # */
+ log_printf("%31s", compatible);
+ free(compatible);
+ /* Print Revision */
+ log_printf("%6d", revision);
+ log_printf("\n");
+ }
+
+ return (PICL_WALK_CONTINUE);
+}
+
+/*
+ * return the first compatible value
+ */
+int
+huron_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
+{
+ int err;
+ picl_prophdl_t proph;
+ picl_propinfo_t pinfo;
+ picl_prophdl_t tblh;
+ picl_prophdl_t rowproph;
+ char *pval;
+
+ err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
+ &pinfo, &proph);
+ if (err != PICL_SUCCESS)
+ return (err);
+
+ if (pinfo.type == PICL_PTYPE_CHARSTRING) {
+ pval = malloc(pinfo.size);
+ if (pval == NULL)
+ return (PICL_FAILURE);
+ err = picl_get_propval(proph, pval, pinfo.size);
+ if (err != PICL_SUCCESS) {
+ free(pval);
+ return (err);
+ }
+ *outbuf = pval;
+ return (PICL_SUCCESS);
+ }
+
+ if (pinfo.type != PICL_PTYPE_TABLE)
+ return (PICL_FAILURE);
+
+ /* get first string from table */
+ err = picl_get_propval(proph, &tblh, pinfo.size);
+ if (err != PICL_SUCCESS)
+ return (err);
+
+ err = picl_get_next_by_row(tblh, &rowproph);
+ if (err != PICL_SUCCESS)
+ return (err);
+
+ err = picl_get_propinfo(rowproph, &pinfo);
+ if (err != PICL_SUCCESS)
+ return (err);
+
+ pval = malloc(pinfo.size);
+ if (pval == NULL)
+ return (PICL_FAILURE);
+
+ err = picl_get_propval(rowproph, pval, pinfo.size);
+ if (err != PICL_SUCCESS) {
+ free(pval);
+ return (err);
+ }
+
+ *outbuf = pval;
+ return (PICL_SUCCESS);
+}
+
+int64_t
+huron_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
+{
+ int err;
+ picl_prophdl_t proph;
+ picl_propinfo_t pinfo;
+ int8_t int8v;
+ int16_t int16v;
+ int32_t int32v;
+ int64_t int64v;
+
+ err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
+ if (err != PICL_SUCCESS) {
+ *ret = err;
+ return (0);
+ }
+
+ /*
+ * If it is not an int, uint or byte array prop, return failure
+ */
+ if ((pinfo.type != PICL_PTYPE_INT) &&
+ (pinfo.type != PICL_PTYPE_UNSIGNED_INT) &&
+ (pinfo.type != PICL_PTYPE_BYTEARRAY)) {
+ *ret = PICL_FAILURE;
+ return (0);
+ }
+
+ switch (pinfo.size) {
+ case sizeof (int8_t):
+ err = picl_get_propval(proph, &int8v, sizeof (int8v));
+ *ret = err;
+ return (int8v);
+ case sizeof (int16_t):
+ err = picl_get_propval(proph, &int16v, sizeof (int16v));
+ *ret = err;
+ return (int16v);
+ case sizeof (int32_t):
+ err = picl_get_propval(proph, &int32v, sizeof (int32v));
+ *ret = err;
+ return (int32v);
+ case sizeof (int64_t):
+ err = picl_get_propval(proph, &int64v, sizeof (int64v));
+ *ret = err;
+ return (int64v);
+ default: /* not supported size */
+ *ret = PICL_FAILURE;
+ return (0);
+ }
+}
diff --git a/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.h b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.h
new file mode 100644
index 0000000000..d73fa48259
--- /dev/null
+++ b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/huron.h
@@ -0,0 +1,126 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Sun4v Platform header file.
+ *
+ * called when :
+ * machine_type == huron
+ *
+ */
+
+#ifndef _HURON_H
+#define _HURON_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HURON_2U_PLATFORM "SUNW,SPARC-Enterprise-T5220"
+#define HURON_1U_PLATFORM "SUNW,SPARC-Enterprise-T5120"
+#define HURON_PCIE_COMP 30
+#define HURON_XAUI_COMP 17
+#define NO_SLOT -1
+#define NET_COMP_NUM 3
+#define MOTHERBOARD "MB"
+#define HURON_SWITCH_A "PCI-SWITCH0"
+#define HURON_SWITCH_B "PCI-SWITCH1"
+#define HURON_SWITCH_C "PCI-SWITCH2"
+#define SOUTHBRIDGE "southbridge"
+#define OPHIR "GBE"
+#define NETWORK "network"
+#define PCIE "/PCIE"
+#define HURON_SIU "/siu@80"
+#define HURON_SWITCH_A_PATH "/pci@0/pci@0"
+#define HURON_SWITCH_B_PATH "/pci@0/pci@0/pci@1/pci@0"
+#define HURON_SWITCH_C_PATH "/pci@0/pci@0/pci@8/pci@0"
+#define HURON_NETWORK_0 "/pci@0/pci@0/pci@1/pci@0/pci@2/network@0"
+#define HURON_NETWORK_1 "/pci@0/pci@0/pci@1/pci@0/pci@2/network@0,1"
+#define HURON_NETWORK_2 "/pci@0/pci@0/pci@1/pci@0/pci@3/network@0"
+#define HURON_NETWORK_3 "/pci@0/pci@0/pci@1/pci@0/pci@3/network@0,1"
+#define HURON_USB_0 "/pci@0/pci@0/pci@1/pci@0/pci@1/pci@0/usb@1c"
+#define HURON_USB_1 "/pci@0/pci@0/pci@1/pci@0/pci@1/pci@0/usb@1c,1"
+#define HURON_USB_2 "/pci@0/pci@0/pci@1/pci@0/pci@1/pci@0/usb@1c,2"
+#define HURON_USB_3 "/pci@0/pci@0/pci@1/pci@0/pci@1/pci@0/usb@1c,3"
+#define HURON_IDE "/pci@0/pci@0/pci@1/pci@0/pci@1/pci@0/ide@1f"
+#define HURON_PCIE_SLOT1 "/pci@0/pci@0/pci@8/pci@0/pci@2"
+#define HURON_PCIE_SLOT2 "/pci@0/pci@0/pci@8/pci@0/pci@1"
+#define HURON_PCIE_SLOT3 "/pci@0/pci@0/pci@8/pci@0/pci@8"
+#define HURON_PCIE_SLOT4 "/pci@0/pci@0/pci@9"
+#define HURON_PCIE_SLOT5 "/pci@0/pci@0/pci@8/pci@0/pci@a"
+#define HURON_PCIE_SLOT6 "/pci@0/pci@0/pci@8/pci@0/pci@9"
+#define HURON_LSI_PATH "/pci@0/pci@0/pci@2/scsi@0"
+#define HURON_N2_XAUI0 "/siu@80/network@0"
+#define HURON_N2_XAUI1 "/siu@80/network@1"
+#define SAS_SATA_HBA "SAS-SATA-HBA"
+
+
+
+/*
+ * Property names
+ */
+#define OBP_PROP_REG "reg"
+#define OBP_PROP_CLOCK_FREQ "clock-frequency"
+#define OBP_PROP_BOARD_NUM "board#"
+#define OBP_PROP_REVISION_ID "revision-id"
+#define OBP_PROP_VERSION_NUM "version#"
+#define OBP_PROP_BOARD_TYPE "board_type"
+#define OBP_PROP_ECACHE_SIZE "ecache-size"
+#define OBP_PROP_IMPLEMENTATION "implementation#"
+#define OBP_PROP_MASK "mask#"
+#define OBP_PROP_COMPATIBLE "compatible"
+#define OBP_PROP_BANNER_NAME "banner-name"
+#define OBP_PROP_MODEL "model"
+#define OBP_PROP_66MHZ_CAPABLE "66mhz-capable"
+#define OBP_PROP_FBC_REG_ID "fbc_reg_id"
+#define OBP_PROP_VERSION "version"
+#define OBP_PROP_INSTANCE "instance"
+
+/*
+ * Function Headers
+ */
+
+
+/* local functions */
+
+int huron_pci_callback(picl_nodehdl_t pcih, void *args);
+int huron_hw_rev_callback(picl_nodehdl_t pcih, void *args);
+int huron_get_first_compatible_value(picl_nodehdl_t nodeh,
+ char **outbuf);
+int64_t huron_get_int_propval(picl_nodehdl_t modh, char *prop_name,
+ int *ret);
+void huron_get_nac(char bus_type[], char path[], int s,
+ char name[], char loc[], int size);
+int huron_get_name(picl_nodehdl_t nodeh, char name[], int size);
+int huron_get_model(picl_nodehdl_t nodeh, char model[], int size);
+int huron_get_path(picl_nodehdl_t nodeh, char path[], int size);
+int huron_get_class(picl_nodehdl_t nodeh, char piclclass[], int size);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HURON_H */
diff --git a/usr/src/lib/libprtdiag_psr/sparc/ontario/common/ontario.c b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/ontario.c
index 9ec2c25c35..d64d2f3ef4 100644
--- a/usr/src/lib/libprtdiag_psr/sparc/ontario/common/ontario.c
+++ b/usr/src/lib/libprtdiag_psr/sparc/ontario/common/ontario.c
@@ -55,6 +55,7 @@
#include "erie.h"
#include "pelton.h"
#include "stpaul.h"
+#include "huron.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
@@ -331,6 +332,13 @@ sun4v_display_pci(picl_nodehdl_t plafh)
strlen(STPAUL_PLATFORM))) == 0) {
(void) picl_walk_tree_by_class(plafh, "pciex",
"pciex", stpaul_pci_callback);
+ } else if ((strncmp(platbuf, HURON_1U_PLATFORM,
+ strlen(HURON_1U_PLATFORM)) == 0) || (strncmp(platbuf,
+ HURON_2U_PLATFORM, strlen(HURON_2U_PLATFORM)) == 0)) {
+ (void) picl_walk_tree_by_class(plafh, "siu",
+ "siu", huron_pci_callback);
+ (void) picl_walk_tree_by_class(plafh, "pciex",
+ "pciex", huron_pci_callback);
} else {
(void) picl_walk_tree_by_class(plafh, "pciex", "pciex",
erie_pci_callback);
@@ -479,7 +487,7 @@ sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh)
Prom_node *pnode;
char *value;
char platbuf[MAXSTRLEN];
- char *fmt = "%-20s %-40s %-30s %-9s";
+ char *fmt = "%-20s %-45s %-30s %-9s";
log_printf(dgettext(TEXT_DOMAIN, "\n"
"========================= HW Revisions "
@@ -500,7 +508,7 @@ sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh)
"------------------\n"));
log_printf(fmt, "Location", "Path", "Device", "Revision\n", 0);
log_printf(fmt, "--------------------",
- "----------------------------------------",
+ "---------------------------------------------",
"------------------------------",
"---------\n", 0);
@@ -542,6 +550,17 @@ sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh)
"network", stpaul_hw_rev_callback);
(void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2",
stpaul_hw_rev_callback);
+ } else if ((strncmp(platbuf, HURON_1U_PLATFORM,
+ strlen(HURON_1U_PLATFORM)) == 0) || (strncmp(platbuf,
+ HURON_2U_PLATFORM, strlen(HURON_2U_PLATFORM)) == 0)) {
+ (void) picl_walk_tree_by_class(plafh, "pciex",
+ "pciex", huron_hw_rev_callback);
+ (void) picl_walk_tree_by_class(plafh, "siu",
+ "siu", huron_hw_rev_callback);
+ (void) picl_walk_tree_by_class(plafh, "network",
+ "network", huron_hw_rev_callback);
+ (void) picl_walk_tree_by_class(plafh, "scsi-2", "scsi-2",
+ huron_hw_rev_callback);
} else {
(void) picl_walk_tree_by_class(plafh, "pciex", "pciex",
erie_hw_rev_callback);
diff --git a/usr/src/pkgdefs/Makefile b/usr/src/pkgdefs/Makefile
index 9486b77b65..944526486e 100644
--- a/usr/src/pkgdefs/Makefile
+++ b/usr/src/pkgdefs/Makefile
@@ -74,6 +74,10 @@ sparc_SUBDIRS= \
SUNWldomu.v \
SUNWluxd.u \
SUNWluxl \
+ SUNWn2cp.v \
+ SUNWn2cpact.v \
+ SUNWniumx.v \
+ SUNWnxge.v \
SUNWonmtst.u \
SUNWonmtst.v \
SUNWiopc.u \
@@ -90,6 +94,7 @@ sparc_SUBDIRS= \
SUNWstc.u \
SUNWus.u \
SUNWust1.v \
+ SUNWust2.v \
SUNWwrsa.u \
SUNWwrsd.u \
SUNWwrsm.u \
diff --git a/usr/src/pkgdefs/SUNWcakr.v/prototype_com b/usr/src/pkgdefs/SUNWcakr.v/prototype_com
index 8b21689c69..1655ef2feb 100644
--- a/usr/src/pkgdefs/SUNWcakr.v/prototype_com
+++ b/usr/src/pkgdefs/SUNWcakr.v/prototype_com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -59,6 +58,7 @@ d none platform/sun4v/kernel/drv 755 root sys
f none platform/sun4v/kernel/drv/bge.conf 644 root sys
f none platform/sun4v/kernel/drv/trapstat.conf 644 root sys
f none platform/sun4v/kernel/drv/ncp.conf 644 root sys
+f none platform/sun4v/kernel/drv/n2rng.conf 644 root sys
d none platform/sun4v/kernel/drv/sparcv9 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/bge 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/ebus 755 root sys
@@ -71,6 +71,7 @@ f none platform/sun4v/kernel/drv/sparcv9/trapstat 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/vnex 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/glvc 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/ncp 755 root sys
+f none platform/sun4v/kernel/drv/sparcv9/n2rng 755 root sys
f none platform/sun4v/kernel/drv/sparcv9/mdesc 755 root sys
f none platform/sun4v/kernel/drv/mdesc.conf 644 root sys
d none platform/sun4v/kernel/misc 755 root sys
diff --git a/usr/src/pkgdefs/SUNWcart200.v/prototype_com b/usr/src/pkgdefs/SUNWcart200.v/prototype_com
index 858c9c151c..228b2a9840 100644
--- a/usr/src/pkgdefs/SUNWcart200.v/prototype_com
+++ b/usr/src/pkgdefs/SUNWcart200.v/prototype_com
@@ -58,6 +58,8 @@ s none platform/SUNW,Sun-Fire-T200/lib=../sun4v/lib
s none platform/SUNW,Sun-Fire-T1000=sun4v
s none platform/SUNW,Netra-T2000=SUNW,Sun-Fire-T200
s none platform/SUNW,Netra-CP3060/lib=../sun4v/lib
+s none platform/SUNW,SPARC-Enterprise-T5220=sun4v
+s none platform/SUNW,SPARC-Enterprise-T5120=sun4v
s none platform/SUNW,SPARC-Enterprise-T2000=SUNW,Sun-Fire-T200
s none platform/SUNW,SPARC-Enterprise-T1000=sun4v
s none platform/SUNW,Sun-Blade-T6300=sun4v
diff --git a/usr/src/pkgdefs/SUNWcryptoint/postinstall b/usr/src/pkgdefs/SUNWcryptoint/postinstall
index cb0692865f..f0f1d4307d 100644
--- a/usr/src/pkgdefs/SUNWcryptoint/postinstall
+++ b/usr/src/pkgdefs/SUNWcryptoint/postinstall
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -63,9 +62,10 @@ fi
if [ $start -eq 1 ]
then
+ cp -p $kcfconf $tmpfile || error=yes
sed -e "/$pkg_start/,/$pkg_end/d" $kcfconf > $tmpfile || error=yes
else
- cp $kcfconf $tmpfile || error=yes
+ cp -p $kcfconf $tmpfile || error=yes
fi
#
diff --git a/usr/src/pkgdefs/SUNWcryptoint/preremove b/usr/src/pkgdefs/SUNWcryptoint/preremove
index 0278b7b851..42ed19b4c5 100644
--- a/usr/src/pkgdefs/SUNWcryptoint/preremove
+++ b/usr/src/pkgdefs/SUNWcryptoint/preremove
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -63,6 +62,7 @@ fi
if [ $start -eq 1 ]
then
+ cp -p $kcfconf $tmpfile || error=yes
sed -e "/$pkg_start/,/$pkg_end/d" $kcfconf > $tmpfile || error=yes
if [ "$error" = no ]
then
diff --git a/usr/src/pkgdefs/SUNWcryptoint/prototype_com b/usr/src/pkgdefs/SUNWcryptoint/prototype_com
index d2c77766c2..0b83781f2f 100644
--- a/usr/src/pkgdefs/SUNWcryptoint/prototype_com
+++ b/usr/src/pkgdefs/SUNWcryptoint/prototype_com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -52,6 +51,7 @@ f none etc/certs/SUNWosnetSolaris 644 root sys
d none etc/crypto 755 root sys
d none etc/crypto/certs 755 root sys
f none etc/crypto/certs/SUNWosnet 644 root sys
+f none etc/crypto/certs/SUNWosnetLimited 644 root sys
d none kernel 755 root sys
d none kernel/crypto 755 root sys
d none kernel/drv 755 root sys
diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_com b/usr/src/pkgdefs/SUNWcsr/prototype_com
index aca370edd5..9c92f840fa 100644
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsr/prototype_com
@@ -111,6 +111,7 @@ e pkcs11confbase etc/crypto/pkcs11.conf 644 root sys
d none etc/crypto/certs 755 root sys
f none etc/crypto/certs/CA 644 root sys
f none etc/crypto/certs/SUNW_SunOS_5.10 644 root sys
+f none etc/crypto/certs/SUNW_SunOS_5.11_Limited 644 root sys
d none etc/crypto/crls 755 root sys
f none etc/datemsk 444 root sys
s none etc/dcopy=../usr/sbin/dcopy
diff --git a/usr/src/pkgdefs/SUNWkvmt200.v/prototype_com b/usr/src/pkgdefs/SUNWkvmt200.v/prototype_com
index aa13212c2e..a6b28b7492 100644
--- a/usr/src/pkgdefs/SUNWkvmt200.v/prototype_com
+++ b/usr/src/pkgdefs/SUNWkvmt200.v/prototype_com
@@ -93,6 +93,14 @@ s none usr/platform/SUNW,Sun-Fire-T1000=SUNW,Sun-Fire-T200
#
s none usr/platform/SUNW,Netra-T2000=SUNW,Sun-Fire-T200
#
+# add huron 1U link
+#
+s none usr/platform/SUNW,SPARC-Enterprise-T5120=SUNW,Sun-Fire-T200
+#
+# add huron 2U link
+#
+s none usr/platform/SUNW,SPARC-Enterprise-T5220=SUNW,Sun-Fire-T200
+#
# add erie fujitsu link
#
s none usr/platform/SUNW,SPARC-Enterprise-T1000=SUNW,Sun-Fire-T200
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/Makefile b/usr/src/pkgdefs/SUNWn2cp.v/Makefile
new file mode 100644
index 0000000000..96e3011c82
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/Makefile
@@ -0,0 +1,38 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+
+.KEEP_STATE:
+
+all: $(FILES) postinstall preremove
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/pkginfo.tmpl b/usr/src/pkgdefs/SUNWn2cp.v/pkginfo.tmpl
new file mode 100644
index 0000000000..a39cdcc8a7
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/pkginfo.tmpl
@@ -0,0 +1,59 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWn2cp"
+NAME="UltraSPARC-T2 Crypto Provider"
+ARCH="sparc.sun4v"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+CATEGORY="system"
+DESC="UltraSPARC-T2 Crypto Provider"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/postinstall b/usr/src/pkgdefs/SUNWn2cp.v/postinstall
new file mode 100644
index 0000000000..22fc10d112
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/postinstall
@@ -0,0 +1,117 @@
+#! /bin/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# install the UltraSPARC-T2 Crypto Provider device driver
+#
+
+PATH="/usr/bin:/usr/sbin:${PATH}"
+export PATH
+
+# Add hardware provider section for the n2cp driver
+# to /etc/crypto/kcf.conf
+
+pkg_start="# Start $PKGINST"
+pkg_end="# End $PKGINST"
+kcfconf=${BASEDIR}/etc/crypto/kcf.conf
+tmpfile=/tmp/$$kcfconf
+error=no
+
+#
+# If /etc/crypto/kcf.conf doesn't exist, bail immediately
+#
+if [ ! -f "$kcfconf" ]
+then
+ echo "$0: ERROR - $kcfconf doesn't exist"
+ exit 2
+fi
+
+#
+# If the package has been already installed, remove old entries
+#
+start=0
+end=0
+egrep -s "$pkg_start" $kcfconf && start=1
+egrep -s "$pkg_end" $kcfconf && end=1
+
+if [ $start -ne $end ] ; then
+ echo "$0: missing Start or End delimiters for $PKGINST in $kcfconf."
+ echo "$0: $kcfconf may be corrupted and was not updated."
+ error=yes
+ exit 2
+fi
+
+if [ $start -eq 1 ]
+then
+ cp -p $kcfconf $tmpfile || error=yes
+ sed -e "/$pkg_start/,/$pkg_end/d" $kcfconf > $tmpfile || error=yes
+else
+ cp -p $kcfconf $tmpfile || error=yes
+fi
+
+#
+# Append the delimiters for this package
+#
+echo "$pkg_start driver_names=n2cp" >> $tmpfile || error=yes
+echo "$pkg_end" >> $tmpfile || error=yes
+
+#
+# Install the updated config file and clean up the tmp file
+#
+if [ "$error" = no ]
+then
+ mv $tmpfile $kcfconf || error=yes
+fi
+rm -f $tmpfile
+
+#
+# All done, if any of the steps above fail, report the error
+#
+if [ "$error" = yes ]
+then
+ echo "$0: ERROR - failed to update $kcfconf."
+ exit 2
+fi
+
+NAMEMAJOR="${BASEDIR}/etc/name_to_major"
+
+if [ "${BASEDIR:=/}" = "/" ]
+then
+ ADD_DRV="/usr/sbin/add_drv"
+else
+ ADD_DRV="/usr/sbin/add_drv -b ${BASEDIR}"
+fi
+
+grep -w n2cp ${NAMEMAJOR} > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ $ADD_DRV -i "SUNW,n2-cwq" n2cp || exit 1
+fi
+
+exit 0
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/preremove b/usr/src/pkgdefs/SUNWn2cp.v/preremove
new file mode 100644
index 0000000000..27bc9f6fd5
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/preremove
@@ -0,0 +1,105 @@
+#! /bin/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+#
+# Preremove script for SUNWn2cp.v.
+#
+# This script removes the hardware provider section for the n2cp
+# driver from /etc/crypto/kcf.conf
+#
+DRV=n2cp
+
+NAMEMAJOR="${BASEDIR}/etc/name_to_major"
+
+#
+# Determine if we are on an alternate BASEDIR
+#
+if [ "${BASEDIR:=/}" = "/" ]
+then
+ REM_DRV="/usr/sbin/rem_drv"
+else
+ REM_DRV="/usr/sbin/rem_drv -b ${BASEDIR}"
+fi
+
+#
+# Remove the driver, but only if this has not already been done.
+#
+grep -w "${DRV}" ${NAMEMAJOR} > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+ ${REM_DRV} ${DRV} || exit 1
+fi
+
+pkg_start="# Start $PKGINST"
+pkg_end="# End $PKGINST"
+kcfconf=${BASEDIR}/etc/crypto/kcf.conf
+tmpfile=/tmp/$$kcfconf
+error=no
+
+#
+# If /etc/crypto/kcf.conf doesn't exist, bail immediately
+#
+if [ ! -f "$kcfconf" ]
+then
+ echo "$0: ERROR - $kcfconf doesn't exist"
+ exit 2
+fi
+
+#
+# Strip all entries belonging to this package
+#
+start=0
+end=0
+egrep -s "$pkg_start" $kcfconf && start=1
+egrep -s "$pkg_end" $kcfconf && end=1
+
+if [ $start -ne $end ] ; then
+ echo "$0: missing Start or End delimiters for $PKGINST in $kcfconf."
+ echo "$0: $kcfconf may be corrupted and was not updated."
+ error=yes
+ exit 2
+fi
+
+if [ $start -eq 1 ]
+then
+ cp -p $kcfconf $tmpfile || error=yes
+ sed -e "/$pkg_start/,/$pkg_end/d" $kcfconf > $tmpfile || error=yes
+ if [ "$error" = no ]
+ then
+ mv $tmpfile $kcfconf || error=yes
+ fi
+ rm -f $tmpfile
+else
+ exit 0
+fi
+
+if [ "$error" = yes ]
+then
+ echo "$0: ERROR - failed to update $kcfconf."
+ exit 2
+fi
+exit 0
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/prototype_com b/usr/src/pkgdefs/SUNWn2cp.v/prototype_com
new file mode 100644
index 0000000000..9c9c76509a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/prototype_com
@@ -0,0 +1,55 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+i postinstall
+i preremove
+#
+# source locations relative to the prototype file
+#
+# SUNWn2cp.v
+#
+d none platform 755 root sys
+d none platform/sun4v 755 root sys
+d none platform/sun4v/kernel 755 root sys
+d none platform/sun4v/kernel/drv 755 root sys
+f none platform/sun4v/kernel/drv/n2cp.conf 644 root sys
+d none platform/sun4v/kernel/drv/sparcv9 755 root sys
+f none platform/sun4v/kernel/drv/sparcv9/n2cp 755 root sys
diff --git a/usr/src/pkgdefs/SUNWn2cp.v/prototype_sparc b/usr/src/pkgdefs/SUNWn2cp.v/prototype_sparc
new file mode 100644
index 0000000000..490c56e986
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cp.v/prototype_sparc
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+# SUNWn2cp.v
+#
diff --git a/usr/src/pkgdefs/SUNWn2cpact.v/Makefile b/usr/src/pkgdefs/SUNWn2cpact.v/Makefile
new file mode 100644
index 0000000000..9e4cf38085
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cpact.v/Makefile
@@ -0,0 +1,36 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(FILES)
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWn2cpact.v/depend b/usr/src/pkgdefs/SUNWn2cpact.v/depend
new file mode 100644
index 0000000000..fa4568464a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cpact.v/depend
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This package information file defines software dependencies associated
+# with the pkg. You can define three types of pkg dependencies with this file:
+# P indicates a prerequisite for installation
+# I indicates an incompatible package
+# R indicates a reverse dependency
+# <pkg.abbr> see pkginfo(4), PKG parameter
+# <name> see pkginfo(4), NAME parameter
+# <version> see pkginfo(4), VERSION parameter
+# <arch> see pkginfo(4), ARCH parameter
+# <type> <pkg.abbr> <name>
+# (<arch>)<version>
+# (<arch>)<version>
+# ...
+# <type> <pkg.abbr> <name>
+# ...
+
+P SUNWcakr Core Solaris Kernel Architecture (Root)
+P SUNWn2cp UltraSPARC-T2 Crypto Provider
diff --git a/usr/src/pkgdefs/SUNWn2cpact.v/pkginfo.tmpl b/usr/src/pkgdefs/SUNWn2cpact.v/pkginfo.tmpl
new file mode 100644
index 0000000000..8cdf8466c5
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cpact.v/pkginfo.tmpl
@@ -0,0 +1,59 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWn2cpact"
+NAME="UltraSPARC-T2 Crypto Provider Activation File"
+ARCH="sparc.sun4v"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+CATEGORY="system"
+DESC="UltraSPARC-T2 Crypto Provider Activation File"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
diff --git a/usr/src/pkgdefs/SUNWn2cpact.v/prototype_com b/usr/src/pkgdefs/SUNWn2cpact.v/prototype_com
new file mode 100644
index 0000000000..7123b3b2ac
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cpact.v/prototype_com
@@ -0,0 +1,52 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+#
+# source locations relative to the prototype file
+#
+# SUNWn2cpact.v
+#
+d none platform 755 root sys
+d none platform/sun4v 755 root sys
+d none platform/sun4v/kernel 755 root sys
+d none platform/sun4v/kernel/drv 755 root sys
+d none platform/sun4v/kernel/drv/sparcv9 755 root sys
+f none platform/sun4v/kernel/drv/sparcv9/n2cp.esa 644 root sys
diff --git a/usr/src/pkgdefs/SUNWn2cpact.v/prototype_sparc b/usr/src/pkgdefs/SUNWn2cpact.v/prototype_sparc
new file mode 100644
index 0000000000..2d880ddca5
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWn2cpact.v/prototype_sparc
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+# SUNWn2cpact.v
+#
diff --git a/usr/src/pkgdefs/SUNWniumx.v/Makefile b/usr/src/pkgdefs/SUNWniumx.v/Makefile
new file mode 100644
index 0000000000..f8f1d88c8a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/Makefile
@@ -0,0 +1,38 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+
+.KEEP_STATE:
+
+all: $(FILES) postinstall postremove
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWniumx.v/pkginfo.tmpl b/usr/src/pkgdefs/SUNWniumx.v/pkginfo.tmpl
new file mode 100644
index 0000000000..e2b92f1f9c
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/pkginfo.tmpl
@@ -0,0 +1,48 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWniumx"
+NAME="UltraSPARC-T2 NIU nexus driver"
+ARCH="sparc.sun4v"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+MAXINST="1000"
+CATEGORY="system"
+DESC="UltraSPARC-T2 NIU nexus driver"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
diff --git a/usr/src/pkgdefs/SUNWniumx.v/postinstall b/usr/src/pkgdefs/SUNWniumx.v/postinstall
new file mode 100644
index 0000000000..20568755c8
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/postinstall
@@ -0,0 +1,132 @@
+#!/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+# 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 \
+'"SUNW,niumx"
+'\
+-m '* 0666 root sys' niumx
diff --git a/usr/src/pkgdefs/SUNWniumx.v/postremove b/usr/src/pkgdefs/SUNWniumx.v/postremove
new file mode 100644
index 0000000000..a8244030f8
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/postremove
@@ -0,0 +1,38 @@
+#!/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+BD=${BASEDIR:-/}
+if grep -w niumx $BD/etc/name_to_major > /dev/null 2>&1
+then
+ rem_drv -b ${BD} niumx
+ if [ $? -ne 0 ]
+ then
+ exit 1
+ fi
+fi
+exit 0
diff --git a/usr/src/pkgdefs/SUNWniumx.v/prototype_com b/usr/src/pkgdefs/SUNWniumx.v/prototype_com
new file mode 100644
index 0000000000..bcad3c40a8
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/prototype_com
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+i postinstall
+i postremove
+
+#
+# source locations relative to the prototype file
+#
+# SUNWniumx.v
+#
diff --git a/usr/src/pkgdefs/SUNWniumx.v/prototype_sparc b/usr/src/pkgdefs/SUNWniumx.v/prototype_sparc
new file mode 100644
index 0000000000..e59dfc078b
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWniumx.v/prototype_sparc
@@ -0,0 +1,57 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+#
+# SUNWniumx.v
+#
+d none platform 755 root sys
+d none platform/sun4v 755 root sys
+d none platform/sun4v/kernel 755 root sys
+d none platform/sun4v/kernel/drv 755 root sys
+d none platform/sun4v/kernel/drv/sparcv9 755 root sys
+f none platform/sun4v/kernel/drv/sparcv9/niumx 755 root sys
diff --git a/usr/src/pkgdefs/SUNWnxge.v/Makefile b/usr/src/pkgdefs/SUNWnxge.v/Makefile
new file mode 100644
index 0000000000..f8f1d88c8a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/Makefile
@@ -0,0 +1,38 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+
+.KEEP_STATE:
+
+all: $(FILES) postinstall postremove
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWnxge.v/pkginfo.tmpl b/usr/src/pkgdefs/SUNWnxge.v/pkginfo.tmpl
new file mode 100644
index 0000000000..e97609b6c2
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/pkginfo.tmpl
@@ -0,0 +1,49 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWnxge"
+NAME="UltraSPARC-T2 NIU leaf driver"
+ARCH="sparc.sun4v"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+MAXINST="1000"
+CATEGORY="system"
+DESC="UltraSPARC-T2 NIU leaf driver"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+
diff --git a/usr/src/pkgdefs/SUNWnxge.v/postinstall b/usr/src/pkgdefs/SUNWnxge.v/postinstall
new file mode 100644
index 0000000000..5b20f3b639
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/postinstall
@@ -0,0 +1,132 @@
+#!/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+# 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 \
+'"SUNW,niusl"
+'\
+-m '* 0666 root sys' nxge
diff --git a/usr/src/pkgdefs/SUNWnxge.v/postremove b/usr/src/pkgdefs/SUNWnxge.v/postremove
new file mode 100644
index 0000000000..7de250ac87
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/postremove
@@ -0,0 +1,38 @@
+#!/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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+BD=${BASEDIR:-/}
+if grep -w nxge $BD/etc/name_to_major > /dev/null 2>&1
+then
+ rem_drv -b ${BD} nxge
+ if [ $? -ne 0 ]
+ then
+ exit 1
+ fi
+fi
+exit 0
diff --git a/usr/src/pkgdefs/SUNWnxge.v/prototype_com b/usr/src/pkgdefs/SUNWnxge.v/prototype_com
new file mode 100644
index 0000000000..f6a8fbdd93
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/prototype_com
@@ -0,0 +1,47 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+i postinstall
+i postremove
+#
+# source locations relative to the prototype file
+#
+# SUNWnxge.v
+#
diff --git a/usr/src/pkgdefs/SUNWnxge.v/prototype_sparc b/usr/src/pkgdefs/SUNWnxge.v/prototype_sparc
new file mode 100644
index 0000000000..167ecf3f70
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWnxge.v/prototype_sparc
@@ -0,0 +1,57 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+#
+# SUNWnxge.v
+#
+d none platform 755 root sys
+d none platform/sun4v 755 root sys
+d none platform/sun4v/kernel 755 root sys
+d none platform/sun4v/kernel/drv 755 root sys
+d none platform/sun4v/kernel/drv/sparcv9 755 root sys
+f none platform/sun4v/kernel/drv/sparcv9/nxge 755 root sys
diff --git a/usr/src/pkgdefs/SUNWust2.v/Makefile b/usr/src/pkgdefs/SUNWust2.v/Makefile
new file mode 100644
index 0000000000..fbabdf4e9e
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWust2.v/Makefile
@@ -0,0 +1,38 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+DATAFILES += depend
+
+.KEEP_STATE:
+
+all: $(FILES)
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWust2.v/pkginfo.tmpl b/usr/src/pkgdefs/SUNWust2.v/pkginfo.tmpl
new file mode 100644
index 0000000000..60c0a21b81
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWust2.v/pkginfo.tmpl
@@ -0,0 +1,55 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWust2"
+NAME="UltraSPARC-T2 (Root)"
+ARCH="sparc.sun4v"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+CATEGORY="system"
+DESC="UltraSPARC-T2 core kernel software"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
diff --git a/usr/src/pkgdefs/SUNWust2.v/prototype_com b/usr/src/pkgdefs/SUNWust2.v/prototype_com
new file mode 100644
index 0000000000..c26ff2303a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWust2.v/prototype_com
@@ -0,0 +1,55 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+#
+# source locations relative to the prototype file
+#
+# SUNWust2.v
+#
+d none platform 755 root sys
+d none platform/sun4v 755 root sys
+d none platform/sun4v/kernel 755 root sys
+d none platform/sun4v/kernel/cpu 755 root sys
+d none platform/sun4v/kernel/cpu/sparcv9 755 root sys
+f none platform/sun4v/kernel/cpu/sparcv9/SUNW,UltraSPARC-T2 755 root sys
+d none platform/sun4v/kernel/pcbe 755 root sys
+d none platform/sun4v/kernel/pcbe/sparcv9 755 root sys
+f none platform/sun4v/kernel/pcbe/sparcv9/pcbe.SUNW,UltraSPARC-T2 755 root sys
diff --git a/usr/src/pkgdefs/SUNWust2.v/prototype_sparc b/usr/src/pkgdefs/SUNWust2.v/prototype_sparc
new file mode 100644
index 0000000000..8a443e8217
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWust2.v/prototype_sparc
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+#
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+# SUNWust2.v
+#
diff --git a/usr/src/req.flg b/usr/src/req.flg
index ce4fa07c02..e11bca3309 100644
--- a/usr/src/req.flg
+++ b/usr/src/req.flg
@@ -38,6 +38,8 @@ echo_file usr/src/tools/abi/etc/ABI_sparc.db
echo_file usr/src/tools/abi/etc/ABI_i386.db
echo_file usr/src/tools/abi/etc/exceptions
echo_file usr/closed/cmd/cmd-crypto/etc/certs/SUNWosnet
+echo_file usr/closed/cmd/cmd-crypto/etc/certs/SUNWosnetLimited
echo_file usr/closed/cmd/cmd-crypto/etc/certs/SUNWosnetSolaris
echo_file usr/closed/cmd/cmd-crypto/etc/keys/SUNWosnet
+echo_file usr/closed/cmd/cmd-crypto/etc/keys/SUNWosnetLimited
echo_file usr/closed/cmd/cmd-crypto/etc/keys/SUNWosnetSolaris
diff --git a/usr/src/tools/findunref/exception_list b/usr/src/tools/findunref/exception_list
index 1a7523d525..30a4da3e90 100644
--- a/usr/src/tools/findunref/exception_list
+++ b/usr/src/tools/findunref/exception_list
@@ -122,6 +122,8 @@
#
# Ignore files that get used during a EXPORT_SRC or CRYPT_SRC build only.
#
+./closed/uts/sun4v/io/n2cp/Makefile
+./closed/uts/sun4v/io/ncp/Makefile
./src/common/crypto/aes/Makefile
./src/common/crypto/arcfour/Makefile
./src/common/crypto/blowfish/Makefile
@@ -139,7 +141,6 @@
./src/uts/common/gssapi/include/Makefile
./src/uts/common/gssapi/mechs/dummy/Makefile
./src/uts/common/gssapi/mechs/krb5/Makefile
-./closed/uts/sun4v/io/ncp/Makefile
./src/xmod
#
diff --git a/usr/src/uts/Makefile.targ b/usr/src/uts/Makefile.targ
index e6bb07bb73..5f898515f8 100644
--- a/usr/src/uts/Makefile.targ
+++ b/usr/src/uts/Makefile.targ
@@ -251,6 +251,12 @@ $(ROOT_CONFFILE): $(SRC_CONFFILE) $(ROOT_CONFFILE:%/$(CONFFILE)=%)
$(INS.conffile)
#
+# Targets for '.esa' (activation) file installation.
+#
+$(ROOT_ACTFILE):
+ $(INS.actfile)
+
+#
# Targets for creating links between common platforms. ROOT_PLAT_LINKS
# are are the /platform level while ROOT_PLAT_LINKS_2 are one level
# down (/platform/`uname -i`/{lib|sbin|kernel}.
diff --git a/usr/src/uts/Makefile.uts b/usr/src/uts/Makefile.uts
index 0e8b22e1de..508560c90e 100644
--- a/usr/src/uts/Makefile.uts
+++ b/usr/src/uts/Makefile.uts
@@ -289,12 +289,19 @@ ROOT_CONFFILE_32 = $(ROOTMODULE).conf
ROOT_CONFFILE_64 = $(ROOTMODULE:%/$(SUBDIR64)/$(MODULE)=%/$(MODULE)).conf
ROOT_CONFFILE = $(ROOT_CONFFILE_$(CLASS))
+ROOT_ACTFILE = $(ROOTMODULE).esa
+
INS.conffile= \
$(RM) $@; $(INS) -s -m $(CFILEMODE) -f $(@D) $(SRC_CONFFILE)
$(CH)INS.conffile= \
$(INS) -s -m $(CFILEMODE) -u $(OWNER) -g $(GROUP) -f $(@D) $(SRC_CONFFILE)
+INS.actfile= \
+ $(RM) $@; $(INS) -s -m $(CFILEMODE) -f $(@D) $(BINARY).esa
+$(CH)INS.actfile= \
+ $(INS) -s -m $(CFILEMODE) -u $(OWNER) -g $(GROUP) -f $(@D) $(BINARY).esa
+
#
# The CTF merge of child kernel modules is performed against one of the genunix
# modules. For Intel builds, all modules will be used with a single genunix:
diff --git a/usr/src/uts/common/io/pcie.c b/usr/src/uts/common/io/pcie.c
index 5cc42e3e9c..55cc0e7a52 100644
--- a/usr/src/uts/common/io/pcie.c
+++ b/usr/src/uts/common/io/pcie.c
@@ -37,7 +37,10 @@
#include <sys/pcie.h>
#include <sys/pci_cap.h>
#include <sys/pcie_impl.h>
+#include <sys/pci_impl.h>
+static int pcie_get_bdf_from_dip(dev_info_t *dip, uint32_t *bdf);
+dev_info_t *pcie_get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip);
#ifdef DEBUG
uint_t pcie_debug_flags = 0;
@@ -127,10 +130,24 @@ pcie_initchild(dev_info_t *cdip)
uint8_t bcr;
uint16_t command_reg, status_reg;
uint16_t cap_ptr;
+ pci_parent_data_t *pd_p;
if (pci_config_setup(cdip, &config_handle) != DDI_SUCCESS)
return (DDI_FAILURE);
+ /* Allocate memory for pci parent data */
+ pd_p = kmem_zalloc(sizeof (pci_parent_data_t), KM_SLEEP);
+
+ /*
+ * Retrieve and save BDF and PCIE2PCI bridge's secondary bus
+ * information in the parent private data structure.
+ */
+ if (pcie_get_bdf_from_dip(cdip, &pd_p->pci_bdf) != DDI_SUCCESS)
+ goto fail;
+
+ pd_p->pci_sec_bus = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, 0,
+ "pcie2pci-sec-bus", 0);
+
/*
* Determine the configuration header type.
*/
@@ -168,14 +185,20 @@ pcie_initchild(dev_info_t *cdip)
}
if ((PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_ptr))
- != DDI_FAILURE)
+ != DDI_FAILURE) {
pcie_enable_errors(cdip, config_handle);
- pci_config_teardown(&config_handle);
+ pd_p->pci_phfun = (pci_config_get8(config_handle,
+ cap_ptr + PCIE_DEVCAP) & PCIE_DEVCAP_PHTM_FUNC_MASK) >> 3;
+ }
+ ddi_set_parent_data(cdip, (void *)pd_p);
+ pci_config_teardown(&config_handle);
return (DDI_SUCCESS);
fail:
cmn_err(CE_WARN, "PCIE init child failed\n");
+ kmem_free(pd_p, sizeof (pci_parent_data_t));
+ pci_config_teardown(&config_handle);
return (DDI_FAILURE);
}
@@ -208,6 +231,12 @@ void
pcie_uninitchild(dev_info_t *cdip)
{
ddi_acc_handle_t config_handle;
+ pci_parent_data_t *pd_p;
+
+ if (pd_p = ddi_get_parent_data(cdip)) {
+ ddi_set_parent_data(cdip, NULL);
+ kmem_free(pd_p, sizeof (pci_parent_data_t));
+ }
if (pci_config_setup(cdip, &config_handle) != DDI_SUCCESS)
return;
@@ -472,6 +501,39 @@ pcie_disable_errors(dev_info_t *dip, ddi_acc_handle_t config_handle)
PCIE_AER_SUCE_BITS);
}
+static int
+pcie_get_bdf_from_dip(dev_info_t *dip, uint32_t *bdf)
+{
+ pci_regspec_t *regspec;
+ int reglen;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ "reg", (int **)&regspec, (uint_t *)&reglen) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ if (reglen < (sizeof (pci_regspec_t) / sizeof (int))) {
+ ddi_prop_free(regspec);
+ return (DDI_FAILURE);
+ }
+
+ /* Get phys_hi from first element. All have same bdf. */
+ *bdf = (regspec->pci_phys_hi & (PCI_REG_BDFR_M ^ PCI_REG_REG_M)) >> 8;
+
+ ddi_prop_free(regspec);
+ return (DDI_SUCCESS);
+}
+
+dev_info_t *
+pcie_get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip)
+{
+ dev_info_t *cdip = rdip;
+
+ for (; ddi_get_parent(cdip) != dip; cdip = ddi_get_parent(cdip))
+ ;
+
+ return (cdip);
+}
+
#ifdef DEBUG
/*
* This is a temporary stop gap measure.
diff --git a/usr/src/uts/common/os/kcpc.c b/usr/src/uts/common/os/kcpc.c
index 569344e8ca..4ed3b8b354 100644
--- a/usr/src/uts/common/os/kcpc.c
+++ b/usr/src/uts/common/os/kcpc.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -891,7 +890,15 @@ kcpc_hw_overflow_intr(caddr_t arg1, caddr_t arg2)
if (pcbe_ops == NULL ||
(bitmap = pcbe_ops->pcbe_overflow_bitmap()) == 0)
return (DDI_INTR_UNCLAIMED);
-
+#ifdef N2_ERRATUM_134
+ /*
+ * Check if any of the supported counters overflowed. If
+ * not, it's a spurious overflow trap (Niagara2 1.x silicon
+ * bug). Ignore this trap.
+ */
+ if ((bitmap & ((1 <<cpc_ncounters)-1)) == 0)
+ return (DDI_INTR_CLAIMED);
+#endif
/*
* Prevent any further interrupts.
*/
diff --git a/usr/src/uts/common/sys/pci_impl.h b/usr/src/uts/common/sys/pci_impl.h
index e5fb73d135..3e492e52ed 100644
--- a/usr/src/uts/common/sys/pci_impl.h
+++ b/usr/src/uts/common/sys/pci_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -124,6 +123,22 @@ extern int memlist_count(struct memlist *);
#endif /* __i386 || __amd64 */
/*
+ * Parent private data structure for PCI/PCI-X/PCIe devices.
+ */
+typedef struct pci_parent_data {
+ uint32_t pci_bdf; /* BDF for pci/pci-x/pcie */
+ uint8_t pci_sec_bus; /* PCIE2PCI bridge's secondary bus */
+ uint8_t pci_phfun; /* Phantom funs for pci-x/pcie */
+} pci_parent_data_t;
+
+#define PCI_GET_BDF(dip) \
+ ((pci_parent_data_t *)DEVI((dip))->devi_parent_data)->pci_bdf
+#define PCI_GET_SEC_BUS(dip) \
+ ((pci_parent_data_t *)DEVI((dip))->devi_parent_data)->pci_sec_bus
+#define PCI_GET_PHFUN(dip) \
+ ((pci_parent_data_t *)DEVI((dip))->devi_parent_data)->pci_phfun
+
+/*
* PCI capability related definitions.
*/
diff --git a/usr/src/uts/common/sys/pcie_impl.h b/usr/src/uts/common/sys/pcie_impl.h
index 1d6e552a45..3b8ce839f1 100644
--- a/usr/src/uts/common/sys/pcie_impl.h
+++ b/usr/src/uts/common/sys/pcie_impl.h
@@ -50,6 +50,7 @@ extern void pcie_enable_errors(dev_info_t *dip,
ddi_acc_handle_t config_handle);
extern void pcie_disable_errors(dev_info_t *dip,
ddi_acc_handle_t config_handle);
+extern dev_info_t *pcie_get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip);
extern int pcie_enable_ce(dev_info_t *dip,
ddi_acc_handle_t config_handle);
diff --git a/usr/src/uts/common/sys/sha1.h b/usr/src/uts/common/sys/sha1.h
index f81a1ae45c..87972d8714 100644
--- a/usr/src/uts/common/sys/sha1.h
+++ b/usr/src/uts/common/sys/sha1.h
@@ -34,6 +34,12 @@
extern "C" {
#endif
+/*
+ * NOTE: n2rng (Niagara2 RNG driver) accesses the state field of
+ * SHA1_CTX directly. NEVER change this structure without verifying
+ * compatiblity with n2rng. The important thing is that the state
+ * must be in a field declared as uint32_t state[5].
+ */
/* SHA-1 context. */
typedef struct {
uint32_t state[5]; /* state (ABCDE) */
diff --git a/usr/src/uts/sparc/os/driver_aliases b/usr/src/uts/sparc/os/driver_aliases
index 0631f46325..fc0759ceab 100644
--- a/usr/src/uts/sparc/os/driver_aliases
+++ b/usr/src/uts/sparc/os/driver_aliases
@@ -170,3 +170,6 @@ oplpanel "FJSV,panel"
oplmsu "FJSV,oplmsu"
mc-opl "FJSV,oplmc"
scfd "FJSV,scfc"
+ncp "SUNW,sun4v-ncp"
+ncp "SUNW,n2-mau"
+n2rng "SUNW,n2-rng"
diff --git a/usr/src/uts/sparc/os/name_to_major b/usr/src/uts/sparc/os/name_to_major
index f500ac8dca..7843740bc9 100644
--- a/usr/src/uts/sparc/os/name_to_major
+++ b/usr/src/uts/sparc/os/name_to_major
@@ -214,3 +214,4 @@ dm2s 265
oplkmdrv 266
pxb_bcm 267
pxb_plx 268
+n2rng 269
diff --git a/usr/src/uts/sun4/io/px/px_dma.c b/usr/src/uts/sun4/io/px/px_dma.c
index 0fcc25244a..aa8f3e582d 100644
--- a/usr/src/uts/sun4/io/px/px_dma.c
+++ b/usr/src/uts/sun4/io/px/px_dma.c
@@ -112,6 +112,13 @@ px_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t),
mp->dmai_error.err_fep = NULL;
mp->dmai_error.err_cf = NULL;
+ /*
+ * For a given rdip, set mp->dmai_bdf with the bdf value of px's
+ * immediate child. As we move down the PCIe fabric, this field
+ * may be modified by switch and bridge drivers.
+ */
+ mp->dmai_bdf = PCI_GET_BDF(pcie_get_my_childs_dip(dip, rdip));
+
return (mp);
}
@@ -204,7 +211,6 @@ px_dma_lmts2hdl(dev_info_t *dip, dev_info_t *rdip, px_mmu_t *mmu_p,
mp->dmai_flags |= PX_DMAI_FLAGS_NOCTX;
/* store augumented dev input to mp->dmai_attr */
- mp->dmai_minxfer = lim_p->dlim_minxfer;
mp->dmai_burstsizes = lim_p->dlim_burstsizes;
attr_p = &mp->dmai_attr;
SET_DMAATTR(attr_p, lo, hi, -1, count_max);
@@ -343,7 +349,6 @@ px_dma_attr2hdl(px_t *px_p, ddi_dma_impl_t *mp)
if (PX_DMA_NOCTX(mp->dmai_rdip))
mp->dmai_flags |= PX_DMAI_FLAGS_NOCTX;
- mp->dmai_minxfer = attrp->dma_attr_minxfer;
mp->dmai_burstsizes = attrp->dma_attr_burstsizes;
attrp = &mp->dmai_attr;
SET_DMAATTR(attrp, lo, hi, nocross, count_max);
@@ -718,11 +723,11 @@ px_dvma_map_fast(px_mmu_t *mmu_p, ddi_dma_impl_t *mp)
i *= clustsz;
dvma_pg = mmu_p->dvma_base_pg + i;
- if (px_lib_iommu_map(dip, PCI_TSBID(0, i), npages, attr,
- (void *)mp, 0, MMU_MAP_PFN) != DDI_SUCCESS) {
+ if (px_lib_iommu_map(dip, PCI_TSBID(0, i), npages,
+ PX_ADD_ATTR_EXTNS(attr, mp->dmai_bdf), (void *)mp, 0,
+ MMU_MAP_PFN) != DDI_SUCCESS) {
DBG(DBG_MAP_WIN, dip, "px_dvma_map_fast: "
"px_lib_iommu_map failed\n");
-
return (DDI_FAILURE);
}
@@ -733,8 +738,9 @@ px_dvma_map_fast(px_mmu_t *mmu_p, ddi_dma_impl_t *mp)
ASSERT(PX_HAS_REDZONE(mp));
- if (px_lib_iommu_map(dip, PCI_TSBID(0, i + npages), 1, attr,
- (void *)mp, npages - 1, MMU_MAP_PFN) != DDI_SUCCESS) {
+ if (px_lib_iommu_map(dip, PCI_TSBID(0, i + npages), 1,
+ PX_ADD_ATTR_EXTNS(attr, mp->dmai_bdf), (void *)mp, npages - 1,
+ MMU_MAP_PFN) != DDI_SUCCESS) {
DBG(DBG_MAP_WIN, dip, "px_dvma_map_fast: "
"mapping REDZONE page failed\n");
diff --git a/usr/src/uts/sun4/io/px/px_dma.h b/usr/src/uts/sun4/io/px/px_dma.h
index 4a14d3c721..3a03646a17 100644
--- a/usr/src/uts/sun4/io/px/px_dma.h
+++ b/usr/src/uts/sun4/io/px/px_dma.h
@@ -94,6 +94,7 @@ struct px_dma_impl { /* forthdebug only, keep in sync with ddi_dma_impl_t */
#define dmai_winlst dmai_minfo
#define dmai_pfn0 dmai_sbi
#define dmai_roffset dmai_pool
+#define dmai_bdf dmai_minxfer
#define PX_MP_PFN0(mp) ((px_iopfn_t)(mp)->dmai_pfn0)
#define PX_WINLST(mp) ((px_dma_win_t *)(mp)->dmai_winlst)
#define PX_DEV_ATTR(mp) ((ddi_dma_attr_t *)(mp + 1))
diff --git a/usr/src/uts/sun4/io/px/px_fdvma.c b/usr/src/uts/sun4/io/px/px_fdvma.c
index 5edfa9e40c..2e2b2e60a6 100644
--- a/usr/src/uts/sun4/io/px/px_fdvma.c
+++ b/usr/src/uts/sun4/io/px/px_fdvma.c
@@ -89,8 +89,9 @@ px_fdvma_load(ddi_dma_handle_t h, caddr_t a, uint_t len, uint_t index,
attr = PX_GET_TTE_ATTR(mp->dmai_rflags, mp->dmai_attr.dma_attr_flags);
- if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index), npages, attr,
- (void *)a, 0, MMU_MAP_BUF) != DDI_SUCCESS) {
+ if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index), npages,
+ PX_ADD_ATTR_EXTNS(attr, mp->dmai_bdf), (void *)a, 0,
+ MMU_MAP_BUF) != DDI_SUCCESS) {
cmn_err(CE_WARN, "%s%d: kaddr_load can't get "
"page frame for vaddr %lx", ddi_driver_name(dip),
ddi_get_instance(dip), (uintptr_t)a);
@@ -197,7 +198,6 @@ px_fdvma_reserve(dev_info_t *dip, dev_info_t *rdip, px_t *px_p,
*/
mp->dmai_rdip = rdip;
mp->dmai_rflags = DMP_BYPASSNEXUS | DDI_DMA_READ | DMP_NOSYNC;
- mp->dmai_minxfer = dmareq->dmar_limits->dlim_minxfer;
mp->dmai_burstsizes = dmareq->dmar_limits->dlim_burstsizes;
mp->dmai_mapping = MMU_PTOB(dvma_pg);
mp->dmai_ndvmapages = npages;
diff --git a/usr/src/uts/sun4/io/px/px_ioapi.h b/usr/src/uts/sun4/io/px/px_ioapi.h
index e8ad722fa8..34a1698a03 100644
--- a/usr/src/uts/sun4/io/px/px_ioapi.h
+++ b/usr/src/uts/sun4/io/px/px_ioapi.h
@@ -100,16 +100,36 @@ typedef enum intr_valid_state {
* Attributes for iommu mappings. One or more of the
* following attribute bits stored in a 64-bit unsigned int.
*
- * PCI_MAP_ATTR_READ 0x01 - xfr direction is from memory
- * PCI_MAP_ATTR_WRITE 0x02 - xfr direction is to memory
- * PCI_MAP_ATTR_RO 0x04 - enable relaxed ordering
- *
- * Bits 63:3 are unused and must be set to zero for this
- * version of the specification.
+ * 6 3 0
+ * 3 1 0
+ * 00000000 00000000 00000000 00000000 BBBBBBBB DDDDDFFF 00000000 00PP0LWR
+ *
+ * R: DMA data is transferred from main memory to device.
+ * W: DMA data is transferred from device to main memory.
+ * L: Requested DMA transaction can be relaxed ordered within RC.
+ * P: Value of PCI Express and PCI-X phantom function
+ * configuration. Its encoding is identical to the
+ * "Phantom Function Supported" field of the
+ * "Device Capabilities Register (offset 0x4)"
+ * in the "PCI Express Capability Structure".
+ * The structure is part of a device's config space.
+ * BDF: Bus, device and function number of the device
+ * that is going to issue DMA transactions.
+ * The BDF values are used to guarantee the mapping
+ * only be accessed by the specified device.
+ * If the BDF is set to all 0, RID based protection
+ * will be turned off.
+ *
+ * Relaxed Ordering (L) is advisory. Not all hardware implements a
+ * relaxed ordering attribute. If L attribute is not implemented in
+ * hardware, the implementation is permitted to ignore the L bit.
+ *
+ * Bits 3, 15:6 and 63:32 are unused and must be set to zero for
+ * this version of the specification.
*
* Note: For compatibility with future versions of this
- * specification, the caller must set 63:3 to zero.
- * The implementation shall ignore bits 63:3
+ * specification, the caller must set bits 3, 15:6 and 63:32 to
+ * zero. The implementation shall ignore these bits.
*
* r_addr - 64-bit Real Address.
*
@@ -195,11 +215,17 @@ typedef uint64_t pci_device_t;
((tsbid >> PCI_TSB_INDEX) & PCI_TSB_INDEX_MASK)
typedef enum io_attributes {
- PCI_MAP_ATTR_READ = (uint32_t)0x01,
- PCI_MAP_ATTR_WRITE = (uint32_t)0x02,
- PCI_MAP_ATTR_RO = (uint32_t)0x04
+ PCI_MAP_ATTR_READ = 0x1ull,
+ PCI_MAP_ATTR_WRITE = 0x2ull,
+ PCI_MAP_ATTR_RO = 0x4ull
} io_attributes_t;
+#define PCI_MAP_ATTR_PHFUN 4
+#define PCI_MAP_ATTR_BDF 16
+
+#define PX_ADD_ATTR_EXTNS(attr, bdf) \
+ (attr | (bdf << PCI_MAP_ATTR_BDF))
+
typedef enum io_sync_direction {
IO_SYNC_DEVICE = (uint32_t)0x01,
IO_SYNC_CPU = (uint32_t)0x02
diff --git a/usr/src/uts/sun4/io/px/px_mmu.c b/usr/src/uts/sun4/io/px/px_mmu.c
index 6fd0785592..c3ef404350 100644
--- a/usr/src/uts/sun4/io/px/px_mmu.c
+++ b/usr/src/uts/sun4/io/px/px_mmu.c
@@ -171,8 +171,9 @@ px_mmu_map_pages(px_mmu_t *mmu_p, ddi_dma_impl_t *mp, px_dvma_addr_t dvma_pg,
"npages=0x%x pfn_index=0x%x\n", (uint_t)mmu_p->dvma_base_pg,
(uint_t)pg_index, dvma_pg, (uint_t)npages, (uint_t)pfn_index);
- if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index), npages, attr,
- (void *)mp, pfn_index, MMU_MAP_PFN) != DDI_SUCCESS) {
+ if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index), npages,
+ PX_ADD_ATTR_EXTNS(attr, mp->dmai_bdf), (void *)mp, pfn_index,
+ MMU_MAP_PFN) != DDI_SUCCESS) {
DBG(DBG_MAP_WIN, dip, "px_mmu_map_pages: "
"px_lib_iommu_map failed\n");
@@ -187,8 +188,9 @@ px_mmu_map_pages(px_mmu_t *mmu_p, ddi_dma_impl_t *mp, px_dvma_addr_t dvma_pg,
ASSERT(PX_HAS_REDZONE(mp));
- if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index + npages), 1, attr,
- (void *)mp, pfn_index + npages - 1, MMU_MAP_PFN) != DDI_SUCCESS) {
+ if (px_lib_iommu_map(dip, PCI_TSBID(0, pg_index + npages), 1,
+ PX_ADD_ATTR_EXTNS(attr, mp->dmai_bdf), (void *)mp,
+ pfn_index + npages - 1, MMU_MAP_PFN) != DDI_SUCCESS) {
DBG(DBG_MAP_WIN, dip, "px_mmu_map_pages: mapping "
"REDZONE page failed\n");
diff --git a/usr/src/uts/sun4/io/px/px_obj.h b/usr/src/uts/sun4/io/px/px_obj.h
index 931953ae5c..93a9e6a98b 100644
--- a/usr/src/uts/sun4/io/px/px_obj.h
+++ b/usr/src/uts/sun4/io/px/px_obj.h
@@ -34,6 +34,7 @@ extern "C" {
#include <sys/pcie.h>
#include <sys/pcie_impl.h>
+#include <sys/pci_impl.h>
#include <sys/fm/io/sun4_fire.h>
#include <sys/pci_intr_lib.h>
#include <sys/atomic.h>
diff --git a/usr/src/uts/sun4/io/px/px_pci.c b/usr/src/uts/sun4/io/px/px_pci.c
index a074304735..d365e454e4 100644
--- a/usr/src/uts/sun4/io/px/px_pci.c
+++ b/usr/src/uts/sun4/io/px/px_pci.c
@@ -45,6 +45,7 @@
#include <sys/callb.h>
#include <sys/pcie.h>
#include <sys/pcie_impl.h>
+#include <sys/pci_impl.h>
#include <sys/ddi.h>
#include <sys/sunndi.h>
#include <sys/pci_cap.h>
@@ -71,10 +72,10 @@ static boolean_t pxb_enable_msi = B_TRUE; /* MSI enabled if TRUE, else INTX */
static int pxb_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
off_t, off_t, caddr_t *);
-#ifdef BCM_SW_WORKAROUNDS
static int pxb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_attr_t *attr_p, int (*waitfp)(caddr_t), caddr_t arg,
ddi_dma_handle_t *handlep);
+#ifdef BCM_SW_WORKAROUNDS
static int pxb_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_handle_t handle, enum ddi_dma_ctlops cmd, off_t *offp,
size_t *lenp, caddr_t *objp, uint_t cache_flags);
@@ -107,11 +108,7 @@ static struct bus_ops pxb_bus_ops = {
0,
i_ddi_map_fault,
ddi_dma_map,
-#ifdef BCM_SW_WORKAROUNDS
pxb_dma_allochdl,
-#else
- ddi_dma_allochdl,
-#endif /* BCM_SW_WORKAROUNDS */
ddi_dma_freehdl,
ddi_dma_bindhdl,
ddi_dma_unbindhdl,
@@ -233,7 +230,6 @@ static int pxb_intr_attach(pxb_devstate_t *pxb);
static void pxb_removechild(dev_info_t *);
static int pxb_initchild(dev_info_t *child);
-static dev_info_t *get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip);
static void pxb_create_ranges_prop(dev_info_t *, ddi_acc_handle_t);
int
@@ -416,6 +412,22 @@ pxb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
}
/*
+ * Create an integer property with PCIE2PCI bridge's secondary
+ * PCI bus number. This property will be read and saved in all
+ * PCI and PCI-X device driver's parent private data structure
+ * as part of their init child function.
+ */
+ if (pxb->pxb_port_type == PX_CAP_REG_DEV_TYPE_PCIE2PCI) {
+ if (ndi_prop_update_int(DDI_DEV_T_NONE, pxb->pxb_dip,
+ "pcie2pci-sec-bus", pci_config_get8(config_handle,
+ PCI_BCNF_SECBUS)) != DDI_PROP_SUCCESS) {
+ DBG(DBG_ATTACH, pxb->pxb_dip,
+ "ndi_prop_update_int() failed\n");
+ goto fail;
+ }
+ }
+
+ /*
* Initialize hotplug support on this bus. At minimum
* (for non hotplug bus) this would create ":devctl" minor
* node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
@@ -522,6 +534,9 @@ pxb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
if (pxb->pxb_init_flags & PXB_INIT_FM)
pxb_fm_fini(pxb);
+ (void) ndi_prop_remove(DDI_DEV_T_NONE, pxb->pxb_dip,
+ "pcie2pci-sec-bus");
+
if (pxb->pxb_init_flags & PXB_INIT_CONFIG_HANDLE)
pci_config_teardown(&pxb->pxb_config_handle);
@@ -695,18 +710,6 @@ pxb_ctlops(dev_info_t *dip, dev_info_t *rdip,
}
-static dev_info_t *
-get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip)
-{
- dev_info_t *cdip = rdip;
-
- for (; ddi_get_parent(cdip) != dip; cdip = ddi_get_parent(cdip))
- ;
-
- return (cdip);
-}
-
-
static int
pxb_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
ddi_intr_handle_impl_t *hdlp, void *result)
@@ -729,7 +732,7 @@ pxb_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
"interrupt-map", &len) == DDI_PROP_SUCCESS)
goto done;
- cdip = get_my_childs_dip(dip, rdip);
+ cdip = pcie_get_my_childs_dip(dip, rdip);
/*
* Use the devices reg property to determine its
@@ -1884,8 +1887,6 @@ pxb_id_props(pxb_devstate_t *pxb)
"serialid#", serialid);
}
-#ifdef BCM_SW_WORKAROUNDS
-
/*
* Some PCI-X to PCI-E bridges do not support full 64-bit addressing on the
* PCI-X side of the bridge. We build a special version of this driver for
@@ -1900,8 +1901,9 @@ pxb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_attr_t *attr_p, int (*waitfp)(caddr_t), caddr_t arg,
ddi_dma_handle_t *handlep)
{
- uint64_t lim;
int ret;
+#ifdef BCM_SW_WORKAROUNDS
+ uint64_t lim;
/*
* If the leaf device's limits are outside than what the Broadcom
@@ -1913,6 +1915,8 @@ pxb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
lim = attr_p->dma_attr_addr_hi;
attr_p->dma_attr_addr_hi = MIN(lim, PXB_ADDR_LIMIT_HI);
+#endif /* BCM_SW_WORKAROUNDS */
+
/*
* This is a software workaround to fix the Broadcom 5714/5715 PCIe-PCI
* bridge prefetch bug. Intercept the DMA alloc handle request and set
@@ -1924,12 +1928,23 @@ pxb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
if ((ret = ddi_dma_allochdl(dip, rdip, attr_p, waitfp, arg,
handlep)) == DDI_SUCCESS) {
ddi_dma_impl_t *mp = (ddi_dma_impl_t *)*handlep;
+ dev_info_t *cdip = pcie_get_my_childs_dip(dip, rdip);
+#ifdef BCM_SW_WORKAROUNDS
mp->dmai_inuse |= PX_DMAI_FLAGS_MAP_BUFZONE;
+#endif /* BCM_SW_WORKAROUNDS */
+ /*
+ * For a given rdip, update mp->dmai_bdf with the bdf value
+ * of px_pci's immediate child or secondary bus-id of the
+ * PCIe2PCI bridge.
+ */
+ mp->dmai_minxfer = PCI_GET_SEC_BUS(cdip) ?
+ PCI_GET_SEC_BUS(cdip) : PCI_GET_BDF(cdip);
}
return (ret);
}
+#ifdef BCM_SW_WORKAROUNDS
/*
* FDVMA feature is not supported for any child device of Broadcom 5714/5715
* PCIe-PCI bridge due to prefetch bug. Return failure immediately, so that
@@ -1947,5 +1962,4 @@ pxb_dma_mctl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
return (ddi_dma_mctl(dip, rdip, handle, cmd, offp, lenp, objp,
cache_flags));
}
-
#endif /* BCM_SW_WORKAROUNDS */
diff --git a/usr/src/uts/sun4u/io/pci/pci_pci.c b/usr/src/uts/sun4u/io/pci/pci_pci.c
index 59de4217c8..625e9e86cc 100644
--- a/usr/src/uts/sun4u/io/pci/pci_pci.c
+++ b/usr/src/uts/sun4u/io/pci/pci_pci.c
@@ -37,6 +37,7 @@
#include <sys/ddi_impldefs.h>
#include <sys/ddi_subrdefs.h>
#include <sys/pci.h>
+#include <sys/pci_impl.h>
#include <sys/pci_cap.h>
#include <sys/pci/pci_nexus.h>
#include <sys/pci/pci_regs.h>
@@ -139,6 +140,7 @@ static int ppb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
cred_t *credp, int *rvalp);
static int ppb_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
int flags, char *name, caddr_t valuep, int *lengthp);
+static int ppb_get_bdf_from_dip(dev_info_t *dip, uint32_t *bdf);
static struct cb_ops ppb_cb_ops = {
ppb_open, /* open */
@@ -748,6 +750,7 @@ ppb_initchild(dev_info_t *child)
uchar_t header_type;
uchar_t min_gnt, latency_timer;
ppb_devstate_t *ppb;
+ pci_parent_data_t *pd_p;
/*
* Name the child
@@ -926,6 +929,23 @@ ppb_initchild(dev_info_t *child)
pcix_set_cmd_reg(child, n);
}
+ /* Allocate memory for pci parent data */
+ pd_p = kmem_zalloc(sizeof (pci_parent_data_t), KM_SLEEP);
+
+ /*
+ * Retrieve and save BDF and PCIE2PCI bridge's secondary bus
+ * information in the parent private data structure.
+ */
+ if (ppb_get_bdf_from_dip(child, &pd_p->pci_bdf) != DDI_SUCCESS) {
+ kmem_free(pd_p, sizeof (pci_parent_data_t));
+ pci_config_teardown(&config_handle);
+ return (DDI_FAILURE);
+ }
+
+ pd_p->pci_sec_bus = ddi_prop_get_int(DDI_DEV_T_ANY, child, 0,
+ "pcie2pci-sec-bus", 0);
+
+ ddi_set_parent_data(child, (void *)pd_p);
pci_config_teardown(&config_handle);
return (DDI_SUCCESS);
@@ -935,6 +955,12 @@ static void
ppb_removechild(dev_info_t *dip)
{
ppb_devstate_t *ppb;
+ pci_parent_data_t *pd_p;
+
+ if (pd_p = ddi_get_parent_data(dip)) {
+ ddi_set_parent_data(dip, NULL);
+ kmem_free(pd_p, sizeof (pci_parent_data_t));
+ }
ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
ddi_get_instance(ddi_get_parent(dip)));
@@ -1622,6 +1648,28 @@ static int ppb_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp));
}
+static int
+ppb_get_bdf_from_dip(dev_info_t *dip, uint32_t *bdf)
+{
+ pci_regspec_t *regspec;
+ int reglen;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+ "reg", (int **)&regspec, (uint_t *)&reglen) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ if (reglen < (sizeof (pci_regspec_t) / sizeof (int))) {
+ ddi_prop_free(regspec);
+ return (DDI_FAILURE);
+ }
+
+ /* Get phys_hi from first element. All have same bdf. */
+ *bdf = (regspec->pci_phys_hi & (PCI_REG_BDFR_M ^ PCI_REG_REG_M)) >> 8;
+
+ ddi_prop_free(regspec);
+ return (DDI_SUCCESS);
+}
+
/*
* Initialize our FMA resources
*/
diff --git a/usr/src/uts/sun4v/Makefile.files b/usr/src/uts/sun4v/Makefile.files
index 3c2d65a4db..45a5270dbd 100644
--- a/usr/src/uts/sun4v/Makefile.files
+++ b/usr/src/uts/sun4v/Makefile.files
@@ -118,6 +118,7 @@ ROOTNEX_OBJS += mach_rootnex.o
PX_OBJS += px_lib4v.o px_err.o px_tools_4v.o px_hcall.o
FPC_OBJS += fpc-impl-4v.o fpc-asm-4v.o
TRAPSTAT_OBJS += trapstat.o
+NIUMX_OBJS += niumx.o
#
# CPU/Memory Error Injector (memtest) sun4v driver
@@ -157,6 +158,7 @@ PLATSVC_OBJS = platsvc.o mdeg.o
# Performance Counter BackEnd (PCBE) Modules
#
NI_PCBE_OBJS = niagara_pcbe.o
+N2_PCBE_OBJS = niagara2_pcbe.o
#
# cpu modules
@@ -166,6 +168,8 @@ CPU_OBJ += $(OBJS_DIR)/mach_cpu_module.o
GENERIC_OBJS = generic.o generic_copy.o common_asm.o
NIAGARACPU_OBJS = niagara.o niagara_copy.o common_asm.o niagara_perfctr.o
NIAGARACPU_OBJS += niagara_asm.o
+NIAGARA2CPU_OBJS = niagara2.o niagara_copy.o common_asm.o niagara_perfctr.o
+NIAGARA2CPU_OBJS += niagara2_asm.o
#
# platform module
@@ -176,7 +180,6 @@ PLATMOD_OBJS = platmod.o
#
ALL_DEFS += -Dsun4u -Dsun4v
INC_PATH += -I$(UTSBASE)/sun4v
-
#
# Since assym.h is a derived file, the dependency must be explicit for
# all files including this file. (This is only actually required in the
@@ -187,7 +190,7 @@ INC_PATH += -I$(UTSBASE)/sun4v
ASSYM_DEPS += mach_locore.o
ASSYM_DEPS += module_sfmmu_asm.o
ASSYM_DEPS += generic_asm.o generic_copy.o
-ASSYM_DEPS += niagara_copy.o niagara_asm.o
+ASSYM_DEPS += niagara_copy.o niagara_asm.o niagara2_asm.o
ASSYM_DEPS += mach_subr_asm.o swtch.o
ASSYM_DEPS += mach_interrupt.o mach_xc.o
ASSYM_DEPS += trap_table.o wbuf.o
@@ -198,3 +201,21 @@ ASSYM_DEPS += mach_sfmmu_asm.o sfmmu_asm.o
#
ARCFOUR_OBJS += arcfour.o arcfour_crypt.o
+
+#
+# N2/NIU 10G driver module
+#
+NXGE_OBJS = nxge_mac.o nxge_ipp.o nxge_rxdma.o \
+ nxge_txdma.o nxge_txc.o nxge_main.o \
+ nxge_hw.o nxge_fzc.o nxge_virtual.o \
+ nxge_send.o nxge_classify.o nxge_fflp.o \
+ nxge_fflp_hash.o nxge_ndd.o nxge_kstats.o \
+ nxge_zcp.o nxge_fm.o nxge_espc.o nxge_hcall.o
+
+NXGE_NPI_OBJS = \
+ npi.o npi_mac.o npi_ipp.o \
+ npi_txdma.o npi_rxdma.o npi_txc.o \
+ npi_zcp.o npi_espc.o npi_fflp.o \
+ npi_vir.o
+
+#
diff --git a/usr/src/uts/sun4v/Makefile.rules b/usr/src/uts/sun4v/Makefile.rules
index 6afc3c0da0..082247f2b0 100644
--- a/usr/src/uts/sun4v/Makefile.rules
+++ b/usr/src/uts/sun4v/Makefile.rules
@@ -73,6 +73,17 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/px/%.c
$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/px/%.s
$(COMPILE.s) -o $@ $<
+$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/nxge/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
+$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/nxge/%.s
+ $(COMPILE.s) -o $@ $<
+
+$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/nxge/npi/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/fpc/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -113,6 +124,10 @@ $(OBJS_DIR)/%.o: $(SRC)/common/mdesc/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/sun4v/io/niumx/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(SRC)/common/atomic/sparcv9/%.s
$(COMPILE.s) -o $@ $<
@@ -146,6 +161,18 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/px/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/px/%.s
@($(LHEAD) $(LINT.s) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/niumx/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/nxge/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/nxge/%.s
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/nxge/npi/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4v/io/fpc/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/sun4v/Makefile.sun4v.shared b/usr/src/uts/sun4v/Makefile.sun4v.shared
index 701180c5bc..d113c9c9d2 100644
--- a/usr/src/uts/sun4v/Makefile.sun4v.shared
+++ b/usr/src/uts/sun4v/Makefile.sun4v.shared
@@ -34,6 +34,8 @@
#
PLATFORM = sun4v
LINKED_PLATFORMS += SUNW,Sun-Fire-T1000
+LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T5120
+LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T5220
LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T1000
LINKED_PLATFORMS += SUNW,Sun-Blade-T6300
PROMIF = ieee1275
@@ -323,6 +325,8 @@ DRV_KMODS += ebus
DRV_KMODS += fpc
DRV_KMODS += glvc
DRV_KMODS += mdesc
+DRV_KMODS += niumx
+DRV_KMODS += nxge
DRV_KMODS += px
DRV_KMODS += qcn
DRV_KMODS += rootnex
@@ -338,6 +342,8 @@ DRV_KMODS += vsw
$(CLOSED_BUILD)CLOSED_DRV_KMODS += memtest
$(CLOSED_BUILD)CLOSED_DRV_KMODS += ncp
+$(CLOSED_BUILD)CLOSED_DRV_KMODS += n2cp
+$(CLOSED_BUILD)CLOSED_DRV_KMODS += n2rng
#
# Exec Class Modules (/kernel/exec):
@@ -406,9 +412,10 @@ XMODS +=
#
# cpu modules
#
-CPU_KMODS += generic niagara
+CPU_KMODS += generic niagara niagara2
#
# Performance Counter BackEnd Modules (/usr/kernel/pcbe):
#
PCBE_KMODS += niagara_pcbe
+PCBE_KMODS += niagara2_pcbe
diff --git a/usr/src/uts/sun4v/Makefile.workarounds b/usr/src/uts/sun4v/Makefile.workarounds
index 40a76c9693..632b91da9f 100644
--- a/usr/src/uts/sun4v/Makefile.workarounds
+++ b/usr/src/uts/sun4v/Makefile.workarounds
@@ -34,3 +34,9 @@
WORKAROUND_DEFS =
WORKAROUND_DEFS += -DQCN_POLLING # XXXQ
WORKAROUND_DEFS += -DDO_CORELEVEL_LOADBAL
+
+# The following is required to support Niagara2 1.0
+WORKAROUND_DEFS += -DN2_ERRATUM_49 # %stick_compare{6:0} ignored
+WORKAROUND_DEFS += -DN2_IDLE_WORKAROUND
+WORKAROUND_DEFS += -DN2_ERRATUM_112 # multiple traps for 1 event
+WORKAROUND_DEFS += -DN2_ERRATUM_134 # PMU doesn't set OV bit
diff --git a/usr/src/uts/sun4v/cpu/common_asm.s b/usr/src/uts/sun4v/cpu/common_asm.s
index 094f61770e..76c17215bb 100644
--- a/usr/src/uts/sun4v/cpu/common_asm.s
+++ b/usr/src/uts/sun4v/cpu/common_asm.s
@@ -53,8 +53,25 @@
* caller may depend on these to remain unchanged across the macro.
*/
+#ifdef N2_ERRATUM_49
+/*
+ * Niagara2 does not continuously compare STICK_CMPR and STICK, but it does
+ * so periodically (at least once every 128 cycles). For this reason,
+ * Niagara2 implementations > 1.0 will always returns bits 6:0 of reads of
+ * STICK as 0x7f. This ensures that if software writes a value to
+ * STICK_CMPR that is greater than the value subsequently read from STICK
+ * that a match will occur in the future.
+ *
+ * For Niagara2 1.0, we ensure bits 6:0 return 0x7f here.
+ */
+#define GET_NATIVE_TIME(out, scr1, scr2) \
+ rd STICK, out ;\
+ or out, 0x7f, out
+
+#else /* N2_ERRATUM_49 */
#define GET_NATIVE_TIME(out, scr1, scr2) \
rd STICK, out
+#endif /* N2_ERRATUM_49 */
#define RD_TICKCMPR(out, scr) \
rd STICK_COMPARE, out
diff --git a/usr/src/uts/sun4v/cpu/niagara2.c b/usr/src/uts/sun4v/cpu/niagara2.c
new file mode 100644
index 0000000000..5c713f188d
--- /dev/null
+++ b/usr/src/uts/sun4v/cpu/niagara2.c
@@ -0,0 +1,232 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/archsystm.h>
+#include <sys/machparam.h>
+#include <sys/machsystm.h>
+#include <sys/cpu.h>
+#include <sys/elf_SPARC.h>
+#include <vm/hat_sfmmu.h>
+#include <vm/page.h>
+#include <sys/cpuvar.h>
+#include <sys/async.h>
+#include <sys/cmn_err.h>
+#include <sys/debug.h>
+#include <sys/dditypes.h>
+#include <sys/sunddi.h>
+#include <sys/cpu_module.h>
+#include <sys/prom_debug.h>
+#include <sys/vmsystm.h>
+#include <sys/prom_plat.h>
+#include <sys/sysmacros.h>
+#include <sys/intreg.h>
+#include <sys/machtrap.h>
+#include <sys/ontrap.h>
+#include <sys/ivintr.h>
+#include <sys/atomic.h>
+#include <sys/panic.h>
+#include <sys/dtrace.h>
+#include <sys/simulate.h>
+#include <sys/fault.h>
+#include <sys/niagara2regs.h>
+#include <sys/hsvc.h>
+#include <sys/trapstat.h>
+
+uint_t root_phys_addr_lo_mask = 0xffffffffU;
+char cpu_module_name[] = "SUNW,UltraSPARC-T2";
+
+/*
+ * Hypervisor services information for the NIAGARA2 CPU module
+ */
+static boolean_t niagara2_hsvc_available = B_TRUE;
+static uint64_t niagara2_sup_minor; /* Supported minor number */
+static hsvc_info_t niagara2_hsvc = {
+ HSVC_REV_1, NULL, HSVC_GROUP_NIAGARA2_CPU, NIAGARA2_HSVC_MAJOR,
+ NIAGARA2_HSVC_MINOR, cpu_module_name
+};
+
+void
+cpu_setup(void)
+{
+ extern int mmu_exported_pagesize_mask;
+ extern int cpc_has_overflow_intr;
+ int status;
+
+ /*
+ * Negotiate the API version for Niagara2 specific hypervisor
+ * services.
+ */
+ status = hsvc_register(&niagara2_hsvc, &niagara2_sup_minor);
+ if (status != 0) {
+ cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
+ "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d",
+ niagara2_hsvc.hsvc_modname, niagara2_hsvc.hsvc_group,
+ niagara2_hsvc.hsvc_major, niagara2_hsvc.hsvc_minor, status);
+ niagara2_hsvc_available = B_FALSE;
+ }
+
+ /*
+ * The setup common to all CPU modules is done in cpu_setup_common
+ * routine.
+ */
+ cpu_setup_common(NULL);
+
+ cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
+
+ if ((mmu_exported_pagesize_mask &
+ DEFAULT_SUN4V_MMU_PAGESIZE_MASK) !=
+ DEFAULT_SUN4V_MMU_PAGESIZE_MASK)
+ cmn_err(CE_PANIC, "machine description"
+ " does not have required sun4v page sizes"
+ " 8K, 64K and 4M: MD mask is 0x%x",
+ mmu_exported_pagesize_mask);
+
+ cpu_hwcap_flags = AV_SPARC_VIS | AV_SPARC_VIS2 | AV_SPARC_ASI_BLK_INIT;
+
+ /*
+ * Niagara2 supports a 48-bit subset of the full 64-bit virtual
+ * address space. Virtual addresses between 0x0000800000000000
+ * and 0xffff.7fff.ffff.ffff inclusive lie within a "VA Hole"
+ * and must never be mapped. In addition, software must not use
+ * pages within 4GB of the VA hole as instruction pages to
+ * avoid problems with prefetching into the VA hole.
+ */
+ hole_start = (caddr_t)((1ull << (va_bits - 1)) - (1ull << 32));
+ hole_end = (caddr_t)((0ull - (1ull << (va_bits - 1))) + (1ull << 32));
+
+ /*
+ * Niagara2 has a performance counter overflow interrupt
+ */
+ cpc_has_overflow_intr = 1;
+}
+
+/*
+ * Set the magic constants of the implementation.
+ */
+void
+cpu_fiximp(struct cpu_node *cpunode)
+{
+ /*
+ * The Cache node is optional in MD. Therefore in case "Cache"
+ * node does not exists in MD, set the default L2 cache associativity,
+ * size, linesize.
+ */
+ if (cpunode->ecache_size == 0)
+ cpunode->ecache_size = L2CACHE_SIZE;
+ if (cpunode->ecache_linesize == 0)
+ cpunode->ecache_linesize = L2CACHE_LINESIZE;
+ if (cpunode->ecache_associativity == 0)
+ cpunode->ecache_associativity = L2CACHE_ASSOCIATIVITY;
+}
+
+static int niagara2_cpucnt;
+
+void
+cpu_init_private(struct cpu *cp)
+{
+ extern int niagara_kstat_init(void);
+
+ /*
+ * The cpu_ipipe field is initialized based on the execution
+ * unit sharing information from the MD. It defaults to the
+ * virtual CPU id in the absence of such information.
+ */
+ cp->cpu_m.cpu_ipipe = cpunodes[cp->cpu_id].exec_unit_mapping;
+ if (cp->cpu_m.cpu_ipipe == NO_EU_MAPPING_FOUND)
+ cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id);
+
+ ASSERT(MUTEX_HELD(&cpu_lock));
+ if ((niagara2_cpucnt++ == 0) && (niagara2_hsvc_available == B_TRUE))
+ (void) niagara_kstat_init();
+}
+
+/*ARGSUSED*/
+void
+cpu_uninit_private(struct cpu *cp)
+{
+ extern int niagara_kstat_fini(void);
+
+ ASSERT(MUTEX_HELD(&cpu_lock));
+ if ((--niagara2_cpucnt == 0) && (niagara2_hsvc_available == B_TRUE))
+ (void) niagara_kstat_fini();
+}
+
+/*
+ * On Niagara2, any flush will cause all preceding stores to be
+ * synchronized wrt the i$, regardless of address or ASI. In fact,
+ * the address is ignored, so we always flush address 0.
+ */
+/*ARGSUSED*/
+void
+dtrace_flush_sec(uintptr_t addr)
+{
+ doflush(0);
+}
+
+/*
+ * Trapstat support for Niagara2 processor
+ * The Niagara2 provides HWTW support for TSB lookup and with HWTW
+ * enabled no TSB hit information will be available. Therefore setting
+ * the time spent in TLB miss handler for TSB hits to 0.
+ */
+int
+cpu_trapstat_conf(int cmd)
+{
+ int status = 0;
+
+ switch (cmd) {
+ case CPU_TSTATCONF_INIT:
+ case CPU_TSTATCONF_FINI:
+ case CPU_TSTATCONF_ENABLE:
+ case CPU_TSTATCONF_DISABLE:
+ break;
+ default:
+ status = EINVAL;
+ break;
+ }
+ return (status);
+}
+
+void
+cpu_trapstat_data(void *buf, uint_t tstat_pgszs)
+{
+ tstat_pgszdata_t *tstatp = (tstat_pgszdata_t *)buf;
+ int i;
+
+ for (i = 0; i < tstat_pgszs; i++, tstatp++) {
+ tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_count = 0;
+ tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_time = 0;
+ tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_count = 0;
+ tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_time = 0;
+ tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
+ tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
+ tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
+ tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
+ }
+}
diff --git a/usr/src/uts/sun4v/cpu/niagara2_asm.s b/usr/src/uts/sun4v/cpu/niagara2_asm.s
new file mode 100644
index 0000000000..09dc06cd4b
--- /dev/null
+++ b/usr/src/uts/sun4v/cpu/niagara2_asm.s
@@ -0,0 +1,144 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#if !defined(lint)
+#include "assym.h"
+#endif
+
+/*
+ * Niagara2 processor specific assembly routines
+ */
+
+#include <sys/asm_linkage.h>
+#include <sys/machasi.h>
+#include <sys/machparam.h>
+#include <sys/hypervisor_api.h>
+#include <sys/niagara2regs.h>
+#include <sys/machasi.h>
+#include <sys/niagaraasi.h>
+#include <vm/hat_sfmmu.h>
+
+#if defined(lint)
+/*ARGSUSED*/
+uint64_t
+hv_niagara_getperf(uint64_t perfreg, uint64_t *datap)
+{ return (0); }
+
+/*ARGSUSED*/
+uint64_t
+hv_niagara_setperf(uint64_t perfreg, uint64_t data)
+{ return (0); }
+
+#else /* lint */
+
+ /*
+ * hv_niagara_getperf(uint64_t perfreg, uint64_t *datap)
+ */
+ ENTRY(hv_niagara_getperf)
+ mov %o1, %o4 ! save datap
+ mov HV_NIAGARA2_GETPERF, %o5
+ ta FAST_TRAP
+ brz,a %o0, 1f
+ stx %o1, [%o4]
+1:
+ retl
+ nop
+ SET_SIZE(hv_niagara_getperf)
+
+ /*
+ * hv_niagara_setperf(uint64_t perfreg, uint64_t data)
+ */
+ ENTRY(hv_niagara_setperf)
+ mov HV_NIAGARA2_SETPERF, %o5
+ ta FAST_TRAP
+ retl
+ nop
+ SET_SIZE(hv_niagara_setperf)
+
+#endif /* !lint */
+
+#if defined (lint)
+/*
+ * Invalidate all of the entries within the TSB, by setting the inv bit
+ * in the tte_tag field of each tsbe.
+ *
+ * We take advantage of the fact that the TSBs are page aligned and a
+ * multiple of PAGESIZE to use ASI_BLK_INIT_xxx ASI.
+ *
+ * See TSB_LOCK_ENTRY and the miss handlers for how this works in practice
+ * (in short, we set all bits in the upper word of the tag, and we give the
+ * invalid bit precedence over other tag bits in both places).
+ */
+/*ARGSUSED*/
+void
+cpu_inv_tsb(caddr_t tsb_base, uint_t tsb_bytes)
+{}
+
+#else /* lint */
+
+ ENTRY(cpu_inv_tsb)
+
+ /*
+ * The following code assumes that the tsb_base (%o0) is 256 bytes
+ * aligned and the tsb_bytes count is multiple of 256 bytes.
+ */
+
+ wr %g0, ASI_BLK_INIT_ST_QUAD_LDD_P, %asi
+ set TSBTAG_INVALID, %o2
+ sllx %o2, 32, %o2 ! INV bit in upper 32 bits of the tag
+1:
+ stxa %o2, [%o0+0x0]%asi
+ stxa %o2, [%o0+0x40]%asi
+ stxa %o2, [%o0+0x80]%asi
+ stxa %o2, [%o0+0xc0]%asi
+
+ stxa %o2, [%o0+0x10]%asi
+ stxa %o2, [%o0+0x20]%asi
+ stxa %o2, [%o0+0x30]%asi
+
+ stxa %o2, [%o0+0x50]%asi
+ stxa %o2, [%o0+0x60]%asi
+ stxa %o2, [%o0+0x70]%asi
+
+ stxa %o2, [%o0+0x90]%asi
+ stxa %o2, [%o0+0xa0]%asi
+ stxa %o2, [%o0+0xb0]%asi
+
+ stxa %o2, [%o0+0xd0]%asi
+ stxa %o2, [%o0+0xe0]%asi
+ stxa %o2, [%o0+0xf0]%asi
+
+ subcc %o1, 0x100, %o1
+ bgu,pt %ncc, 1b
+ add %o0, 0x100, %o0
+
+ membar #Sync
+ retl
+ nop
+
+ SET_SIZE(cpu_inv_tsb)
+#endif /* lint */
diff --git a/usr/src/uts/sun4v/cpu/niagara_perfctr.c b/usr/src/uts/sun4v/cpu/niagara_perfctr.c
index 6703d2f238..6bec5932da 100644
--- a/usr/src/uts/sun4v/cpu/niagara_perfctr.c
+++ b/usr/src/uts/sun4v/cpu/niagara_perfctr.c
@@ -31,12 +31,18 @@
#include <sys/sunndi.h>
#include <sys/ddi_impldefs.h>
#include <sys/machsystm.h>
-#include <sys/niagararegs.h>
#include <sys/hypervisor_api.h>
#include <sys/kstat.h>
+#if defined(NIAGARA_IMPL)
+#include <sys/niagararegs.h>
+#elif defined(NIAGARA2_IMPL)
+#include <sys/niagara2regs.h>
+#endif
extern char cpu_module_name[];
+#define NUM_OF_PICS 2
+
/*
* Data structure used to build array of event-names and pcr-mask values
*/
@@ -71,7 +77,10 @@ typedef struct ni_ksinfo {
} ni_ksinfo_t;
static ni_ksinfo_t *ni_dram_kstats[NIAGARA_DRAM_BANKS];
+
+#if defined(NIAGARA_IMPL)
static ni_ksinfo_t *ni_jbus_kstat;
+#endif
typedef struct ni_perf_regs {
uint32_t pcr_reg;
@@ -85,7 +94,6 @@ static ni_perf_regs_t dram_perf_regs[] = {
{HV_NIAGARA_DRAM_CTL3, HV_NIAGARA_DRAM_COUNT3},
};
-
static void ni_create_name_kstat(char *, ni_ksinfo_t *, ni_kev_mask_t *);
static void ni_delete_name_kstat(ni_ksinfo_t *);
@@ -102,7 +110,7 @@ static int ni_perf_debug;
#endif
/*
- * Niagara DRAM Performance Events
+ * Niagara and Niagara2 DRAM Performance Events
*/
static ni_kev_mask_t
niagara_dram_events[] = {
@@ -118,6 +126,7 @@ niagara_dram_events[] = {
};
+#if defined(NIAGARA_IMPL)
/*
* Niagara JBUS Performance Events
*/
@@ -136,6 +145,7 @@ niagara_jbus_events[] = {
{"dok_off_cycles", 0xe},
{"clear_pic", 0xf}
};
+#endif
/*
* Create the picN kstats for DRAM and JBUS events
@@ -186,6 +196,7 @@ niagara_kstat_init()
ni_cntr_kstat_update, ksinfop);
}
+#if defined(NIAGARA_IMPL)
/*
* Create JBUS perf events kstat
*/
@@ -211,6 +222,7 @@ niagara_kstat_init()
ni_jbus_kstat->cntr_ksp = ni_create_cntr_kstat("jbus", 0,
ni_cntr_kstat_update, ni_jbus_kstat);
}
+#endif
}
void
@@ -232,6 +244,7 @@ niagara_kstat_fini()
}
}
+#if defined(NIAGARA_IMPL)
if (ni_jbus_kstat != NULL) {
ni_delete_name_kstat(ni_jbus_kstat);
if (ni_jbus_kstat->cntr_ksp != NULL)
@@ -239,6 +252,7 @@ niagara_kstat_fini()
kmem_free(ni_jbus_kstat, sizeof (ni_ksinfo_t));
ni_jbus_kstat = NULL;
}
+#endif
}
static void
diff --git a/usr/src/uts/sun4v/io/niumx/niumx.c b/usr/src/uts/sun4v/io/niumx/niumx.c
new file mode 100644
index 0000000000..5c7110b742
--- /dev/null
+++ b/usr/src/uts/sun4v/io/niumx/niumx.c
@@ -0,0 +1,965 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Niagara2 Network Interface Unit (NIU) Nexus Driver
+ */
+
+#include <sys/conf.h>
+#include <sys/modctl.h>
+#include <sys/ddi_impldefs.h>
+#include <sys/ddi_subrdefs.h>
+#include <sys/ddi.h>
+#include <sys/sunndi.h>
+#include <sys/sunddi.h>
+#include <sys/open.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/machsystm.h>
+#include <sys/hsvc.h>
+#include <sys/sdt.h>
+#include <sys/hypervisor_api.h>
+#include "niumx_var.h"
+
+
+static int niumx_intr_ops(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
+static int niumx_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
+static int niumx_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
+static int niumx_set_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp, int valid);
+static int niumx_add_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp);
+static int niumx_rem_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp);
+static uint_t niumx_intr_hdlr(void *arg);
+static int niumx_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
+ off_t offset, off_t len, caddr_t *addrp);
+static int niumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
+ ddi_dma_attr_t *attrp,
+ int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep);
+static int niumx_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
+ ddi_dma_handle_t handlep);
+static int niumx_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
+ ddi_dma_handle_t handle, ddi_dma_req_t *dmareq,
+ ddi_dma_cookie_t *cookiep, uint_t *ccountp);
+static int niumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
+ ddi_dma_handle_t handle);
+static int niumx_ctlops(dev_info_t *dip, dev_info_t *rdip,
+ ddi_ctl_enum_t op, void *arg, void *result);
+
+static struct bus_ops niumx_bus_ops = {
+ BUSO_REV,
+ niumx_map,
+ 0,
+ 0,
+ 0,
+ i_ddi_map_fault,
+ 0,
+ niumx_dma_allochdl,
+ niumx_dma_freehdl,
+ niumx_dma_bindhdl,
+ niumx_dma_unbindhdl,
+ 0,
+ 0,
+ 0,
+ niumx_ctlops,
+ ddi_bus_prop_op,
+ 0, /* (*bus_get_eventcookie)(); */
+ 0, /* (*bus_add_eventcall)(); */
+ 0, /* (*bus_remove_eventcall)(); */
+ 0, /* (*bus_post_event)(); */
+ 0, /* (*bus_intr_ctl)(); */
+ 0, /* (*bus_config)(); */
+ 0, /* (*bus_unconfig)(); */
+ 0, /* (*bus_fm_init)(); */
+ 0, /* (*bus_fm_fini)(); */
+ 0, /* (*bus_enter)() */
+ 0, /* (*bus_exit)() */
+ 0, /* (*bus_power)() */
+ niumx_intr_ops /* (*bus_intr_op)(); */
+};
+
+static struct dev_ops niumx_ops = {
+ DEVO_REV, /* devo_rev */
+ 0, /* refcnt */
+ ddi_no_info, /* info */
+ nulldev, /* identify */
+ 0, /* probe */
+ niumx_attach, /* attach */
+ niumx_detach, /* detach */
+ nulldev, /* reset */
+ (struct cb_ops *)0, /* driver operations */
+ &niumx_bus_ops, /* bus operations */
+ 0
+};
+
+/* Module linkage information for the kernel. */
+static struct modldrv modldrv = {
+ &mod_driverops, /* Type of module */
+ "NIU Nexus Driver %I%",
+ &niumx_ops, /* driver ops */
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ (void *)&modldrv,
+ NULL
+};
+
+static void *niumx_state;
+static niumx_ih_t niumx_ihtable[NIUMX_MAX_INTRS];
+
+/*
+ * forward function declarations:
+ */
+static void niumx_removechild(dev_info_t *);
+static int niumx_initchild(dev_info_t *child);
+
+int
+_init(void)
+{
+ int e;
+ if ((e = ddi_soft_state_init(&niumx_state, sizeof (niumx_devstate_t),
+ 1)) == 0 && (e = mod_install(&modlinkage)) != 0)
+ ddi_soft_state_fini(&niumx_state);
+ return (e);
+}
+
+int
+_fini(void)
+{
+ int e;
+ if ((e = mod_remove(&modlinkage)) == 0)
+ ddi_soft_state_fini(&niumx_state);
+ return (e);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
+
+
+/*
+ * Hypervisor VPCI services information for the NIU nexus driver.
+ */
+static uint64_t niumx_vpci_min_ver; /* Neg. VPCI API minor version */
+static hsvc_info_t niumx_hv_vpci = {
+ HSVC_REV_1, NULL, HSVC_GROUP_VPCI, NIUMX_VPCI_MAJOR_VER,
+ NIUMX_VPCI_MINOR_VER, "NIUMX"
+};
+static uint64_t niumx_intr_min_ver; /* Neg. VPCI API minor version */
+static hsvc_info_t niumx_hv_intr = {
+ HSVC_REV_1, NULL, HSVC_GROUP_INTR, NIUMX_INTR_MAJOR_VER,
+ NIUMX_INTR_MINOR_VER, "NIUMX"
+};
+
+static int
+niumx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ int instance = ddi_get_instance(dip);
+ niumx_devstate_t *niumxds_p; /* devstate pointer */
+ niu_regspec_t *reg_p;
+ uint_t reglen;
+ int ret = DDI_SUCCESS;
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, "reg", (int **)&reg_p, &reglen)
+ != DDI_PROP_SUCCESS) {
+ DBG(DBG_ATTACH, dip, "reg lookup failed\n");
+ ret = DDI_FAILURE;
+ goto done;
+ }
+
+ /*
+ * Allocate and get soft state structure.
+ */
+ if (ddi_soft_state_zalloc(niumx_state, instance)
+ != DDI_SUCCESS) {
+ ret = DDI_FAILURE;
+ goto prop_free;
+ }
+ niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
+ instance);
+ niumxds_p->dip = dip;
+ mutex_init(&niumxds_p->niumx_mutex, NULL, MUTEX_DRIVER, NULL);
+
+ DBG(DBG_ATTACH, dip, "soft state alloc'd instance = %d, "
+ "niumxds_p = %p\n", instance, niumxds_p);
+
+ /*
+ * Negotiate the API version for HV VPCI & INTR services.
+ */
+ if ((ret = hsvc_register(&niumx_hv_vpci, &niumx_vpci_min_ver))
+ != H_EOK) {
+ cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
+ "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d\n",
+ niumx_hv_vpci.hsvc_modname, niumx_hv_vpci.hsvc_group,
+ niumx_hv_vpci.hsvc_major, niumx_hv_vpci.hsvc_minor, ret);
+ ret = DDI_FAILURE;
+ goto cleanup;
+ }
+
+ if ((ret = hsvc_register(&niumx_hv_intr, &niumx_intr_min_ver))
+ != H_EOK) {
+ cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
+ "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d\n",
+ niumx_hv_intr.hsvc_modname, niumx_hv_intr.hsvc_group,
+ niumx_hv_intr.hsvc_major, niumx_hv_intr.hsvc_minor, ret);
+ ret = DDI_FAILURE;
+ goto unregister;
+ }
+
+ DBG(DBG_ATTACH, dip, "neg. HV API major 0x%lx minor 0x%lx\n",
+ niumx_hv_vpci.hsvc_major, niumx_vpci_min_ver);
+
+ /* hv devhdl: low 28-bit of 1st "reg" entry's addr.hi */
+ niumxds_p->niumx_dev_hdl = (devhandle_t)(reg_p->addr_high &
+ NIUMX_DEVHDLE_MASK);
+
+ ret = DDI_SUCCESS;
+ goto prop_free;
+
+unregister:
+ (void) hsvc_unregister(&niumx_hv_vpci);
+cleanup:
+ mutex_destroy(&niumxds_p->niumx_mutex);
+ ddi_soft_state_free(niumx_state, ddi_get_instance(dip));
+prop_free:
+ ddi_prop_free(reg_p);
+done:
+ return (ret);
+
+ case DDI_RESUME:
+ default:
+ break;
+ }
+ return (ret);
+}
+
+static int
+niumx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ niumx_devstate_t *niumxds_p;
+
+ switch (cmd) {
+ case DDI_DETACH:
+ (void) hsvc_unregister(&niumx_hv_vpci);
+ (void) hsvc_unregister(&niumx_hv_intr);
+
+ niumxds_p = (niumx_devstate_t *)
+ ddi_get_soft_state(niumx_state, ddi_get_instance(dip));
+
+ mutex_destroy(&niumxds_p->niumx_mutex);
+ ddi_soft_state_free(niumx_state, ddi_get_instance(dip));
+ return (DDI_SUCCESS);
+
+ case DDI_SUSPEND:
+ default:
+ break;
+ }
+ return (DDI_FAILURE);
+}
+
+/*ARGSUSED*/
+int
+niumx_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
+ off_t offset, off_t len, caddr_t *vaddrp)
+{
+ struct regspec p_regspec;
+ ddi_map_req_t p_mapreq;
+ niu_regspec_t *reg_p;
+ int i, rn = mp->map_obj.rnumber, reglen, rnglen, rngnum, ret;
+ niumx_ranges_t *rng_p;
+
+ uint32_t reg_begin, rng_begin;
+
+ DBG(DBG_MAP, dip, "%s%d: mapping %s%d reg %d\n", NAMEINST(dip),
+ NAMEINST(rdip), rn);
+
+ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
+ "reg", (caddr_t)&reg_p, &reglen) != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ if (rn < 0 || (rn >= reglen / sizeof (niu_regspec_t))) {
+ DBG(DBG_MAP, dip, "rnumber out of range: %d\n", rn);
+ kmem_free(reg_p, reglen);
+ return (DDI_ME_RNUMBER_RANGE);
+ }
+
+ /* build regspec up for parent */
+ p_mapreq = *mp; /* dup the whole structure */
+ p_mapreq.map_type = DDI_MT_REGSPEC;
+ p_mapreq.map_obj.rp = &p_regspec;
+
+ if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
+ (caddr_t)&rng_p, &rnglen) != DDI_SUCCESS) {
+ DBG(DBG_MAP, dip, "%s%d: no ranges property\n",
+ ddi_driver_name(dip), ddi_get_instance(dip));
+ kmem_free(reg_p, reglen);
+ return (DDI_FAILURE);
+ }
+
+ /* locate matching ranges record */
+ rngnum = rnglen / sizeof (niumx_ranges_t);
+ for (i = 0, reg_p += rn; i < rngnum; rng_p++, i++) {
+ if (reg_p->addr_high == rng_p->child_hi)
+ break;
+ }
+
+ if (i >= rngnum) {
+ DBG(DBG_MAP, dip, "ranges record for reg[%d] not found.\n", rn);
+ ret = DDI_ME_REGSPEC_RANGE;
+ goto err;
+ }
+
+ /*
+ * validate request has matching bus type and within 4G
+ * limit by comparing addr.hi of "ranges" and child "reg".
+ */
+
+ ASSERT(reg_p->size_high == 0);
+
+ rng_begin = rng_p->child_lo;
+ reg_begin = reg_p->addr_low;
+ /* check to verify reg bounds are within rng bounds */
+ if (reg_begin < rng_begin || (reg_begin + (reg_p->size_low - 1)) >
+ (rng_begin + (rng_p->size_lo - 1))) {
+ DBG(DBG_MAP, dip, "size out of range for reg[%d].\n", rn);
+ ret = DDI_ME_REGSPEC_RANGE;
+ goto err;
+ }
+
+ p_regspec.regspec_bustype = rng_p->parent_hi;
+ p_regspec.regspec_addr = reg_begin - rng_begin + rng_p->parent_lo;
+ p_regspec.regspec_size = reg_p->size_low;
+ DBG(DBG_MAP, dip, "regspec:bus,addr,size = (%x,%x,%x)\n",
+ p_regspec.regspec_bustype, p_regspec.regspec_addr,
+ p_regspec.regspec_size);
+ ret = ddi_map(dip, &p_mapreq, 0, 0, vaddrp);
+ DBG(DBG_MAP, dip, "niumx_map: ret %d.\n", ret);
+err:
+ kmem_free(rng_p - i, rnglen);
+ kmem_free(reg_p - rn, reglen);
+ return (ret);
+}
+
+/*
+ * niumx_ctlops
+ */
+int
+niumx_ctlops(dev_info_t *dip, dev_info_t *rdip,
+ ddi_ctl_enum_t ctlop, void *arg, void *result)
+{
+ niu_regspec_t *reg_p;
+ int reglen, totreg;
+
+ DBG(DBG_CTLOPS, dip, "niumx_ctlops ctlop=%d.\n", ctlop);
+ if (rdip == (dev_info_t *)0)
+ return (DDI_FAILURE);
+
+ switch (ctlop) {
+ case DDI_CTLOPS_REPORTDEV:
+ cmn_err(CE_NOTE, "device: %s@%s, %s%d\n",
+ ddi_node_name(rdip), ddi_get_name_addr(rdip),
+ NAMEINST(rdip));
+ return (DDI_SUCCESS);
+
+ case DDI_CTLOPS_INITCHILD:
+ return (niumx_initchild((dev_info_t *)arg));
+
+ case DDI_CTLOPS_UNINITCHILD:
+ niumx_removechild((dev_info_t *)arg);
+ return (DDI_SUCCESS);
+
+ case DDI_CTLOPS_REGSIZE:
+ case DDI_CTLOPS_NREGS:
+ /* fall through */
+ break;
+ default:
+ DBG(DBG_CTLOPS, dip, "just pass to ddi_cltops.\n");
+ return (ddi_ctlops(dip, rdip, ctlop, arg, result));
+ }
+
+ /* REGSIZE/NREGS */
+
+ *(int *)result = 0;
+
+ if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS |
+ DDI_PROP_CANSLEEP, "reg", (caddr_t)&reg_p, &reglen)
+ != DDI_SUCCESS)
+ return (DDI_FAILURE);
+
+ totreg = reglen / sizeof (niu_regspec_t);
+ if (ctlop == DDI_CTLOPS_NREGS) {
+ DBG(DBG_CTLOPS, (dev_info_t *)dip, "niumx_ctlops NREGS=%d.\n",
+ totreg);
+ *(int *)result = totreg;
+ } else if (ctlop == DDI_CTLOPS_REGSIZE) {
+ int rn;
+ rn = *(int *)arg;
+ if (rn >= totreg) {
+ kmem_free(reg_p, reglen);
+ return (DDI_FAILURE);
+ }
+ *(off_t *)result = (reg_p + rn)->size_low;
+ DBG(DBG_CTLOPS, (dev_info_t *)dip, "rn = %d, REGSIZE=%x.\n",
+ rn, *(off_t *)result);
+ }
+
+ kmem_free(reg_p, reglen);
+ return (DDI_SUCCESS);
+}
+
+static int
+niumx_initchild(dev_info_t *child)
+{
+ char name[MAXNAMELEN];
+ niu_regspec_t *r;
+ uint_t n;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
+ "reg", (int **)&r, &n) != DDI_SUCCESS) {
+ return (DDI_FAILURE);
+ }
+ (void) snprintf(name, MAXNAMELEN, "%x", (r[0].addr_high &
+ NIUMX_FUNC_NUM_MASK));
+ ddi_prop_free(r);
+ ddi_set_name_addr(child, name);
+ return (DDI_SUCCESS);
+}
+
+static void
+niumx_removechild(dev_info_t *dip)
+{
+ ddi_set_name_addr(dip, NULL);
+ ddi_remove_minor_node(dip, NULL);
+ impl_rem_dev_props(dip);
+}
+
+
+
+/*
+ * bus dma alloc handle entry point:
+ */
+/*ARGSUSED*/
+int
+niumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp,
+ int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
+{
+ ddi_dma_impl_t *mp;
+ int sleep = (waitfp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
+
+ DBG(DBG_DMA_ALLOCH, dip, "rdip=%s%d\n", NAMEINST(rdip));
+
+ if (attrp->dma_attr_version != DMA_ATTR_V0) {
+ DBG(DBG_DMA_ALLOCH, (dev_info_t *)dip, "DDI_DMA_BADATTR\n");
+ return (DDI_DMA_BADATTR);
+ }
+
+ /* Caution: we don't use zalloc to enhance performance! */
+ if ((mp = kmem_alloc(sizeof (ddi_dma_impl_t), sleep)) == 0) {
+ DBG(DBG_DMA_ALLOCH, dip, "can't alloc ddi_dma_impl_t\n");
+ return (DDI_FAILURE);
+ }
+ mp->dmai_rdip = rdip;
+ mp->dmai_pfnlst = NULL;
+ mp->dmai_cookie = NULL;
+ mp->dmai_fault = 0;
+ mp->dmai_fault_check = NULL;
+ mp->dmai_fault_notify = NULL;
+
+ mp->dmai_attr = *attrp; /* set requestors attr info */
+
+ DBG(DBG_DMA_ALLOCH, dip, "mp=%p\n", mp);
+
+ *handlep = (ddi_dma_handle_t)mp;
+ return (DDI_SUCCESS);
+}
+
+
+/*
+ * bus dma free handle entry point:
+ */
+/*ARGSUSED*/
+int
+niumx_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
+{
+ ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
+
+ if (mp->dmai_cookie)
+ kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t));
+ kmem_free(mp, sizeof (ddi_dma_impl_t));
+
+ return (DDI_SUCCESS);
+}
+
+
+/*
+ * bus dma bind handle entry point:
+ *
+ * check/enforce DMA type, setup pfn0 and some other key pieces
+ * of this dma request.
+ * Note: this only works with DMA_OTYP_VADDR, and makes use of the known
+ * fact that only contiguous memory blocks will be passed in.
+ * Therefore only one cookie will ever be returned.
+ *
+ * return values:
+ * DDI_DMA_NOMAPPING - can't get valid pfn0, or bad dma type
+ * DDI_DMA_NORESOURCES
+ * DDI_SUCCESS
+ *
+ * dma handle members affected (set on exit):
+ * mp->dmai_object - dmareq->dmar_object
+ * mp->dmai_rflags - dmareq->dmar_flags
+ * mp->dmai_pfn0 - 1st page pfn (if va/size pair and not shadow)
+ * mp->dmai_roffset - initialized to starting page offset
+ * mp->dmai_size - # of total pages of entire object
+ * mp->dmai_cookie - new cookie alloc'd
+ */
+/*ARGSUSED*/
+int
+niumx_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
+ ddi_dma_handle_t handle, ddi_dma_req_t *dmareq,
+ ddi_dma_cookie_t *cookiep, uint_t *ccountp)
+{
+ int (*waitfp)(caddr_t) = dmareq->dmar_fp;
+ ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
+ ddi_dma_obj_t *dobj_p = &dmareq->dmar_object;
+ uint32_t offset;
+ pfn_t pfn0;
+ int ret;
+
+ DBG(DBG_DMA_BINDH, dip, "rdip=%s%d mp=%p dmareq=%p\n", NAMEINST(rdip),
+ mp, dmareq);
+
+ /* first check dma type */
+ mp->dmai_rflags = dmareq->dmar_flags & DMP_DDIFLAGS | DMP_NOSYNC;
+ switch (dobj_p->dmao_type) {
+ case DMA_OTYP_VADDR: {
+ caddr_t vaddr = dobj_p->dmao_obj.virt_obj.v_addr;
+ struct as *as_p = dobj_p->dmao_obj.virt_obj.v_as;
+ struct hat *hat_p = as_p ? as_p->a_hat : kas.a_hat;
+ offset = (ulong_t)vaddr & NIUMX_PAGE_OFFSET;
+ pfn0 = hat_getpfnum(hat_p, vaddr);
+ }
+ break;
+
+ case DMA_OTYP_BUFVADDR:
+ case DMA_OTYP_PAGES:
+ case DMA_OTYP_PADDR:
+ default:
+ cmn_err(CE_WARN, "%s%d requested unsupported dma type %x",
+ NAMEINST(mp->dmai_rdip), dobj_p->dmao_type);
+ ret = DDI_DMA_NOMAPPING;
+ goto err;
+ }
+ if (pfn0 == PFN_INVALID) {
+ cmn_err(CE_WARN, "%s%d: invalid pfn0 for DMA object %p",
+ NAMEINST(dip), (void *)dobj_p);
+ ret = DDI_DMA_NOMAPPING;
+ goto err;
+ }
+ mp->dmai_object = *dobj_p; /* whole object */
+ mp->dmai_pfn0 = (void *)pfn0; /* cache pfn0 */
+ mp->dmai_roffset = offset; /* pg0 offset */
+ mp->dmai_mapping = mp->dmai_roffset | NIUMX_PTOB(pfn0);
+ mp->dmai_size = mp->dmai_object.dmao_size;
+
+ DBG(DBG_DMA_BINDH, dip, "check pfn: mp=%p pfn0=%x\n",
+ mp, mp->dmai_pfn0);
+ if (!(mp->dmai_cookie = kmem_zalloc(sizeof (ddi_dma_cookie_t),
+ waitfp == DDI_DMA_SLEEP ? KM_SLEEP : KM_NOSLEEP))) {
+ ret = DDI_DMA_NORESOURCES;
+ goto err;
+ }
+ mp->dmai_cookie->dmac_laddress = mp->dmai_mapping;
+ mp->dmai_cookie->dmac_size = mp->dmai_size;
+ *ccountp = 1;
+ *cookiep = *mp->dmai_cookie;
+ DBG(DBG_DMA_BINDH, dip, "cookie %" PRIx64 "+%x, count=%d\n",
+ cookiep->dmac_address, cookiep->dmac_size, *ccountp);
+ return (DDI_DMA_MAPPED);
+
+err:
+ DBG(DBG_DMA_BINDH, (dev_info_t *)dip,
+ "niumx_dma_bindhdl error ret=%d\n", ret);
+ return (ret);
+}
+
+/*
+ * bus dma unbind handle entry point:
+ */
+/*ARGSUSED*/
+int
+niumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
+{
+ ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
+
+ DBG(DBG_DMA_UNBINDH, dip, "rdip=%s%d, mp=%p\n",
+ ddi_driver_name(rdip), ddi_get_instance(rdip), handle);
+ if (mp->dmai_cookie) {
+ kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t));
+ mp->dmai_cookie = NULL;
+ }
+
+ return (DDI_SUCCESS);
+}
+
+/*ARGSUSED*/
+int
+niumx_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
+ ddi_intr_handle_impl_t *hdlp, void *result)
+{
+
+ int ret = DDI_SUCCESS;
+
+ DBG(DBG_INTROPS, dip, "niumx_intr_ops: dip=%p rdip=%p intr_op=%x "
+ "handle=%p\n", dip, rdip, intr_op, hdlp);
+
+ switch (intr_op) {
+
+ case DDI_INTROP_SUPPORTED_TYPES:
+ *(int *)result = DDI_INTR_TYPE_FIXED;
+ break;
+ case DDI_INTROP_GETCAP:
+ *(int *)result = DDI_INTR_FLAG_LEVEL;
+ break;
+ case DDI_INTROP_SETCAP:
+ ret = DDI_ENOTSUP;
+ break;
+ case DDI_INTROP_ALLOC:
+ /* scratch1 = count, # of intrs from DDI framework */
+ *(int *)result = hdlp->ih_scratch1;
+ break;
+ case DDI_INTROP_FREE:
+ /* Do we need to do anything here? */
+ break;
+ case DDI_INTROP_GETPRI:
+ *(int *)result = NIUMX_DEFAULT_PIL;
+ break;
+ case DDI_INTROP_SETPRI:
+ ret = DDI_ENOTSUP;
+ break;
+ case DDI_INTROP_ADDISR:
+ ret = niumx_add_intr(dip, rdip, hdlp);
+ break;
+ case DDI_INTROP_REMISR:
+ ret = niumx_rem_intr(dip, rdip, hdlp);
+ break;
+ case DDI_INTROP_ENABLE:
+ ret = niumx_set_intr(dip, rdip, hdlp, HV_INTR_VALID);
+ break;
+ case DDI_INTROP_DISABLE:
+ ret = niumx_set_intr(dip, rdip, hdlp, HV_INTR_NOTVALID);
+ break;
+ case DDI_INTROP_SETMASK:
+ ret = DDI_ENOTSUP;
+ break;
+ case DDI_INTROP_CLRMASK:
+ ret = DDI_ENOTSUP;
+ break;
+ case DDI_INTROP_GETPENDING:
+ ret = DDI_ENOTSUP;
+ break;
+ case DDI_INTROP_NINTRS:
+ case DDI_INTROP_NAVAIL: {
+ devino_t *inos_p;
+ int inoslen;
+ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
+ "interrupts", (caddr_t)&inos_p, &inoslen)
+ != DDI_SUCCESS) {
+ ret = DDI_FAILURE;
+ break;
+ }
+ *(int *)result = inoslen / sizeof (uint32_t);
+ kmem_free(inos_p, inoslen);
+ }
+ break;
+ default:
+ ret = DDI_ENOTSUP;
+ break;
+ }
+
+ DBG(DBG_INTROPS, dip, "niumx_intr_ops: ret=%d\n", ret);
+ return (ret);
+}
+
+int
+niumx_set_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp, int valid)
+{
+ niumx_ih_t *ih_p;
+ devino_t *inos_p;
+ int inoslen, ret = DDI_SUCCESS;
+ uint64_t hvret;
+
+ DBG(DBG_A_INTX, dip, "niumx_set_intr: rdip=%s%d, valid=%d\n",
+ NAMEINST(rdip), valid);
+
+ ASSERT(hdlp->ih_inum < NIUMX_MAX_INTRS);
+
+ /* find the appropriate slot from the fixed table */
+ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
+ "interrupts", (caddr_t)&inos_p, &inoslen) != DDI_SUCCESS) {
+ ret = DDI_FAILURE;
+ goto fail;
+ }
+ ih_p = niumx_ihtable + inos_p[hdlp->ih_inum];
+ DBG(DBG_A_INTX, dip, "enabling (%x,%x,%x)\n", ih_p->ih_inum,
+ ih_p->ih_ino, ih_p->ih_sysino);
+
+ if ((hvret = hvio_intr_setvalid(ih_p->ih_sysino, valid))
+ != H_EOK) {
+ DBG(DBG_A_INTX, dip, "hvio_intr_setvalid failed, ret 0x%x\n",
+ hvret);
+ ret = DDI_FAILURE;
+ }
+ kmem_free(inos_p, inoslen);
+fail:
+ return (ret);
+}
+
+
+
+/*
+ * niumx_add_intr:
+ *
+ * This is the leaf/nexus/HV mapping, now read from "interrupts":
+ *
+ * we have a range of 64 to work with:
+ * [0-15] - reserved
+ * [16] - mac0
+ * [17] - MIF
+ * [18] - SYSERR
+ * [19-26] - func0 Rx (qty. 8)
+ * [27-34] - func0 Tx (qty. 8)
+ * [35] - mac1
+ * [36-43] - func1 Rx (qty. 8)
+ * [44-51] - func1 Tx (qty. 8)
+ *
+ * [52] - Error Interrupt hook
+ */
+int
+niumx_add_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp)
+{
+ niumx_ih_t *ih_p;
+ int inoslen, ret = DDI_SUCCESS;
+ uint64_t hvret;
+ devino_t *inos_p;
+ sysino_t sysino;
+
+ /* FMA Err handling hook */
+ if (dip == rdip) {
+ /*
+ * this is not the leaf calling us, so hardwire in the
+ * FMA interrupt details.
+ */
+ ih_p = niumx_ihtable + NIUMX_EI_IH;
+ ih_p->ih_ino = NIUMX_EI_IH;
+ goto get_sysino;
+ }
+
+ /* get new ino */
+ if (hdlp->ih_inum >= NIUMX_MAX_INTRS) {
+ DBG(DBG_INTR, dip, "error: inum %d out of range\n",
+ hdlp->ih_inum);
+ ret = DDI_FAILURE;
+ goto done;
+ }
+ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
+ "interrupts", (caddr_t)&inos_p, &inoslen) != DDI_SUCCESS) {
+ ret = DDI_FAILURE;
+ goto done;
+ }
+ ih_p = niumx_ihtable + inos_p[hdlp->ih_inum];
+ ih_p->ih_ino = inos_p[hdlp->ih_inum];
+ kmem_free(inos_p, inoslen);
+get_sysino:
+ if ((hvret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip),
+ ih_p->ih_ino, &sysino)) != H_EOK) {
+ DBG(DBG_INTR, dip, "hvio_intr_devino_to_sysino failed, "
+ "ret 0x%x\n", hvret);
+ ret = DDI_FAILURE;
+ goto done;
+ }
+ ih_p->ih_sysino = sysino;
+ ih_p->ih_dip = dip;
+ ih_p->ih_inum = hdlp->ih_inum;
+ ih_p->ih_hdlr = hdlp->ih_cb_func;
+ ih_p->ih_arg1 = hdlp->ih_cb_arg1;
+ ih_p->ih_arg2 = hdlp->ih_cb_arg2;
+
+ DBG(DBG_A_INTX, dip, "niumx_add_intr: rdip=%s%d inum=0x%x "
+ "handler=%p arg1=%p arg2=%p, new ih_p = %p\n", NAMEINST(rdip),
+ hdlp->ih_inum, hdlp->ih_cb_func, hdlp->ih_cb_arg1,
+ hdlp->ih_cb_arg2, ih_p);
+
+ if (hdlp->ih_pri == 0)
+ hdlp->ih_pri = NIUMX_DEFAULT_PIL;
+
+ /* Save sysino value in hdlp */
+ hdlp->ih_vector = ih_p->ih_sysino;
+
+ /* swap in our handler & arg */
+ DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, (ddi_intr_handler_t *)niumx_intr_hdlr,
+ (void *)ih_p, NULL);
+
+ DBG(DBG_A_INTX, dip, "adding (%x,%x,%x)\n", ih_p->ih_inum,
+ ih_p->ih_ino, ih_p->ih_sysino);
+ ret = i_ddi_add_ivintr(hdlp);
+
+ /* Restore orig. interrupt handler & args in handle. */
+ DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, ih_p->ih_hdlr, ih_p->ih_arg1,
+ ih_p->ih_arg2);
+
+ if (ret != DDI_SUCCESS) {
+ DBG(DBG_A_INTX, dip, "i_ddi_add_ivintr error ret=%x\n", ret);
+ goto done;
+ }
+
+ /* select cpu, saving it for removal */
+ ih_p->ih_cpuid = intr_dist_cpuid();
+
+ if ((hvret = hvio_intr_settarget(ih_p->ih_sysino, ih_p->ih_cpuid))
+ != H_EOK) {
+ DBG(DBG_A_INTX, dip, "hvio_intr_settarget failed, ret 0x%x\n",
+ hvret);
+ ret = DDI_FAILURE;
+ }
+done:
+ DBG(DBG_A_INTX, dip, "done, ret = %d, ih_p 0x%p, hdlp 0x%p\n", ih_p,
+ hdlp, ret);
+ return (ret);
+}
+
+/*
+ * niumx_rem_intr:
+ *
+ * This function is called to unregister interrupts.
+ */
+int
+niumx_rem_intr(dev_info_t *dip, dev_info_t *rdip,
+ ddi_intr_handle_impl_t *hdlp)
+{
+ niumx_ih_t *ih_p;
+ cpuid_t curr_cpu;
+ devino_t *inos_p;
+ int inoslen, ret = DDI_SUCCESS;
+ uint64_t hvret;
+
+ ASSERT(hdlp->ih_inum < NIUMX_MAX_INTRS);
+
+ /* find the appropriate slot from the fixed table */
+ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
+ "interrupts", (caddr_t)&inos_p, &inoslen) != DDI_SUCCESS) {
+ ret = DDI_FAILURE;
+ goto fail1;
+ }
+ ih_p = niumx_ihtable + inos_p[hdlp->ih_inum];
+ DBG(DBG_R_INTX, dip, "removing (%x,%x,%x)\n", ih_p->ih_inum,
+ ih_p->ih_ino, ih_p->ih_sysino);
+
+ /* Get the current cpu */
+ if ((hvret = hvio_intr_gettarget(ih_p->ih_sysino, &curr_cpu))
+ != H_EOK) {
+ DBG(DBG_R_INTX, dip, "hvio_intr_gettarget failed, ret 0x%x\n",
+ hvret);
+ ret = DDI_FAILURE;
+ goto fail2;
+ }
+
+ intr_dist_cpuid_rem_device_weight(ih_p->ih_cpuid, rdip);
+
+ hdlp->ih_vector = ih_p->ih_sysino;
+ if (hdlp->ih_vector != NULL) i_ddi_rem_ivintr(hdlp);
+
+ /* clear out this entry */
+ ih_p->ih_ino = NULL;
+fail2:
+ kmem_free(inos_p, inoslen);
+fail1:
+ return (ret);
+}
+
+/*
+ * niumx_intr_hdlr (our interrupt handler)
+ */
+uint_t
+niumx_intr_hdlr(void *arg)
+{
+ niumx_ih_t *ih_p = (niumx_ih_t *)arg;
+ uint_t r;
+
+ DTRACE_PROBE4(interrupt__start, dev_info_t, ih_p->ih_dip, void *,
+ ih_p->ih_hdlr, caddr_t, ih_p->ih_arg1, caddr_t, ih_p->ih_arg2);
+
+ r = (*ih_p->ih_hdlr)(ih_p->ih_arg1, ih_p->ih_arg2);
+
+ DTRACE_PROBE4(interrupt__complete, dev_info_t, ih_p->ih_dip, void *,
+ ih_p->ih_hdlr, caddr_t, ih_p->ih_arg1, int, r);
+ return (r);
+}
+
+#ifdef DEBUG
+uint64_t niumx_debug_flags = 0;
+
+static char *niumx_debug_sym [] = { /* same sequence as niumx_debug_bit */
+ /* 0 */ "attach",
+ /* 1 */ "map",
+ /* 2 */ "nex-ctlops",
+ /* 3 */ "introps",
+ /* 4 */ "intr-add",
+ /* 5 */ "intr-rem",
+ /* 6 */ "intr",
+ /* 7 */ "dma-alloc",
+ /* 8 */ "dma-bind",
+ /* 9 */ "dma-unbind",
+ /* 10 */ "chk-dma-mode"
+};
+
+/*ARGSUSED*/
+void
+niumx_dbg(niumx_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
+{
+ va_list ap;
+ char msgbuf[1024];
+
+ if (!(1ull << bit & niumx_debug_flags))
+ return;
+ va_start(ap, fmt);
+ (void) vsprintf(msgbuf, fmt, ap);
+ va_end(ap);
+ cmn_err(CE_NOTE, "%s: %s", niumx_debug_sym[bit], msgbuf);
+}
+
+#endif /* DEBUG */
diff --git a/usr/src/uts/sun4v/io/niumx/niumx_var.h b/usr/src/uts/sun4v/io/niumx/niumx_var.h
new file mode 100644
index 0000000000..217dc856d7
--- /dev/null
+++ b/usr/src/uts/sun4v/io/niumx/niumx_var.h
@@ -0,0 +1,151 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NMX_H
+#define _SYS_NMX_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum { /* same sequence as niumx_debug_sym[] */
+ /* 0 */ DBG_ATTACH,
+ /* 1 */ DBG_MAP,
+ /* 2 */ DBG_CTLOPS,
+ /* 3 */ DBG_INTROPS,
+ /* 4 */ DBG_A_INTX,
+ /* 5 */ DBG_R_INTX,
+ /* 6 */ DBG_INTR,
+ /* 7 */ DBG_DMA_ALLOCH,
+ /* 8 */ DBG_DMA_BINDH,
+ /* 9 */ DBG_DMA_UNBINDH,
+ /* 10 */ DBG_CHK_MOD
+} niumx_debug_bit_t;
+
+#if defined(DEBUG)
+#define DBG niumx_dbg
+extern void niumx_dbg(niumx_debug_bit_t bit, dev_info_t *dip, char *fmt, ...);
+#else
+#define DBG 0 &&
+#endif /* DEBUG */
+
+typedef uint64_t devhandle_t;
+#define NIUMX_DEVHDLE_MASK 0xFFFFFFF
+typedef uint32_t cpuid_t;
+typedef uint32_t devino_t;
+typedef uint64_t sysino_t;
+
+/*
+ * The following structure represents an interrupt handler control block for
+ * each interrupt added via ddi_intr_add_handler().
+ */
+typedef struct niumx_ih {
+ dev_info_t *ih_dip; /* devinfo structure */
+ uint32_t ih_inum; /* interrupt index, from leaf */
+ devino_t ih_ino; /* INO number, from "interrupts" prop */
+ sysino_t ih_sysino; /* System virtual inumber, from HV */
+ cpuid_t ih_cpuid; /* cpu that ino is targeting */
+ uint_t (*ih_hdlr)(); /* interrupt handler */
+ caddr_t ih_arg1; /* interrupt handler argument #1 */
+ caddr_t ih_arg2; /* interrupt handler argument #2 */
+ struct niumx_ih *ih_next; /* next in the chain */
+} niumx_ih_t;
+
+typedef struct niumx_devstate {
+ dev_info_t *dip;
+ devhandle_t niumx_dev_hdl; /* device handle */
+ kmutex_t niumx_mutex;
+} niumx_devstate_t;
+
+#define NIUMX_FUNC_NUM_MASK 1
+#define NIUMX_MAX_INTRS 64
+
+/* currently Error Interrupt handler slot is hardcoded */
+#define NIUMX_EI_IH 52
+
+/*
+ * flags for overloading dmai_inuse field of the dma request structure:
+ */
+#define dmai_pfnlst dmai_iopte
+#define dmai_pfn0 dmai_sbi
+#define dmai_roffset dmai_pool
+
+#define NIUMX_PAGE_SHIFT 13
+#define NIUMX_PAGE_SIZE (1 << NIUMX_PAGE_SHIFT)
+#define NIUMX_PAGE_MASK ~(NIUMX_PAGE_SIZE - 1)
+#define NIUMX_PAGE_OFFSET (NIUMX_PAGE_SIZE - 1)
+#define NIUMX_PTOB(x) (((uint64_t)(x)) << NIUMX_PAGE_SHIFT)
+
+/* for "ranges" property */
+typedef struct niumx_ranges {
+ uint32_t child_hi;
+ uint32_t child_lo;
+ uint32_t parent_hi;
+ uint32_t parent_lo;
+ uint32_t size_hi;
+ uint32_t size_lo;
+} niumx_ranges_t;
+
+/* IPL of 6 for networking devices */
+#define NIUMX_DEFAULT_PIL 6
+
+typedef struct {
+ uint32_t addr_high;
+ uint32_t addr_low;
+ uint32_t size_high;
+ uint32_t size_low;
+} niu_regspec_t;
+
+/*
+ * HV VPCI & INTR API versioning.
+ *
+ * Currently NIU nexus driver supports VPCI API version 1.0
+ */
+#define NIUMX_VPCI_MAJOR_VER_1 0x1ull
+#define NIUMX_VPCI_MAJOR_VER NIUMX_VPCI_MAJOR_VER_1
+
+#define NIUMX_VPCI_MINOR_VER_0 0x0ull
+#define NIUMX_VPCI_MINOR_VER NIUMX_VPCI_MINOR_VER_0
+
+#define NIUMX_INTR_MAJOR_VER_1 0x1ull
+#define NIUMX_INTR_MAJOR_VER NIUMX_INTR_MAJOR_VER_1
+
+#define NIUMX_INTR_MINOR_VER_0 0x0ull
+#define NIUMX_INTR_MINOR_VER NIUMX_INTR_MINOR_VER_0
+
+#define NAMEINST(dip) ddi_driver_name(dip), ddi_get_instance(dip)
+#define DIP_TO_HANDLE(dip) \
+ ((niumx_devstate_t *)DIP_TO_STATE(dip))->niumx_dev_hdl
+#define DIP_TO_INST(dip) ddi_get_instance(dip)
+#define INST_TO_STATE(inst) ddi_get_soft_state(niumx_state, inst)
+#define DIP_TO_STATE(dip) INST_TO_STATE(DIP_TO_INST(dip))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NMX_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi.c b/usr/src/uts/sun4v/io/nxge/npi/npi.c
new file mode 100644
index 0000000000..3d72c8dbe6
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi.h>
+#include <sys/nxge/nxge_impl.h>
+
+nxge_os_mutex_t npidebuglock;
+int npi_debug_init = 0;
+uint64_t npi_debug_level = 0;
+
+void
+npi_debug_msg(npi_handle_function_t function, uint64_t level, char *fmt, ...)
+{
+ char msg_buffer[1024];
+ char prefix_buffer[32];
+ int cmn_level = CE_CONT;
+ va_list ap;
+
+ if ((level & npi_debug_level) ||
+ (level & NPI_REG_CTL) ||
+ (level & NPI_ERR_CTL)) {
+
+ if (npi_debug_init == 0) {
+ MUTEX_INIT(&npidebuglock, NULL, MUTEX_DRIVER, NULL);
+ npi_debug_init = 1;
+ }
+
+ MUTEX_ENTER(&npidebuglock);
+
+ if (level & NPI_ERR_CTL) {
+ cmn_level = CE_WARN;
+ }
+
+ va_start(ap, fmt);
+ (void) vsprintf(msg_buffer, fmt, ap);
+ va_end(ap);
+
+ (void) sprintf(prefix_buffer, "%s%d(%d):", "npi",
+ function.instance, function.function);
+
+ MUTEX_EXIT(&npidebuglock);
+ cmn_err(cmn_level, "!%s %s\n", prefix_buffer, msg_buffer);
+ }
+}
+
+void
+npi_rtrace_buf_init(rtrace_t *rt)
+{
+ int i;
+
+ rt->next_idx = 0;
+ rt->last_idx = MAX_RTRACE_ENTRIES - 1;
+ rt->wrapped = B_FALSE;
+ for (i = 0; i < MAX_RTRACE_ENTRIES; i++) {
+ rt->buf[i].ctl_addr = TRACE_CTL_INVALID;
+ rt->buf[i].val_l32 = 0;
+ rt->buf[i].val_h32 = 0;
+ }
+}
+
+void
+npi_rtrace_update(npi_handle_t handle, boolean_t wr, rtrace_t *rt,
+ uint32_t addr, uint64_t val)
+{
+ int idx;
+ idx = rt->next_idx;
+ if (wr == B_TRUE)
+ rt->buf[idx].ctl_addr = (addr & TRACE_ADDR_MASK)
+ | TRACE_CTL_WR;
+ else
+ rt->buf[idx].ctl_addr = (addr & TRACE_ADDR_MASK);
+ rt->buf[idx].ctl_addr |= (((handle.function.function
+ << TRACE_FUNC_SHIFT) & TRACE_FUNC_MASK) |
+ ((handle.function.instance
+ << TRACE_INST_SHIFT) & TRACE_INST_MASK));
+ rt->buf[idx].val_l32 = val & 0xFFFFFFFF;
+ rt->buf[idx].val_h32 = (val >> 32) & 0xFFFFFFFF;
+ rt->next_idx++;
+ if (rt->next_idx > rt->last_idx) {
+ rt->next_idx = 0;
+ rt->wrapped = B_TRUE;
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi.h b/usr/src/uts/sun4v/io/nxge/npi/npi.h
new file mode 100644
index 0000000000..b8ec582d2f
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi.h
@@ -0,0 +1,247 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_H
+#define _NPI_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_common_impl.h>
+
+typedef uint32_t npi_status_t;
+
+/* Common Block ID */
+
+#define MAC_BLK_ID 0x1
+#define TXMAC_BLK_ID 0x2
+#define RXMAC_BLK_ID 0x3
+#define MIF_BLK_ID 0x4
+#define IPP_BLK_ID 0x5
+#define TXC_BLK_ID 0x6
+#define TXDMA_BLK_ID 0x7
+#define RXDMA_BLK_ID 0x8
+#define ZCP_BLK_ID 0x9
+#define ESPC_BLK_ID 0xa
+#define FFLP_BLK_ID 0xb
+#define PHY_BLK_ID 0xc
+#define ETHER_SERDES_BLK_ID 0xd
+#define PCIE_SERDES_BLK_ID 0xe
+#define VIR_BLK_ID 0xf
+
+/* Common HW error code */
+/* HW unable to exit from reset state. */
+#define RESET_FAILED 0x81
+
+/* Write operation failed on indirect write. */
+#define WRITE_FAILED 0x82
+/* Read operation failed on indirect read. */
+#define READ_FAILED 0x83
+
+/* Error code boundary */
+
+#define COMMON_SW_ERR_START 0x40
+#define COMMON_SW_ERR_END 0x4f
+#define BLK_SPEC_SW_ERR_START 0x50
+#define BLK_SPEC_SW_ERR_END 0x7f
+#define COMMON_HW_ERR_START 0x80
+#define COMMON_HW_ERR_END 0x8f
+#define BLK_SPEC_HW_ERR_START 0x90
+#define BLK_SPEC_HW_ERR_END 0xbf
+
+#define IS_PORT 0x00100000
+#define IS_CHAN 0x00200000
+
+/* Common SW errors code */
+
+#define PORT_INVALID 0x41 /* Invalid port number */
+#define CHANNEL_INVALID 0x42 /* Invalid dma channel number */
+#define OPCODE_INVALID 0x43 /* Invalid opcode */
+#define REGISTER_INVALID 0x44 /* Invalid register number */
+#define COUNTER_INVALID 0x45 /* Invalid counter number */
+#define CONFIG_INVALID 0x46 /* Invalid config input */
+#define LOGICAL_PAGE_INVALID 0x47 /* Invalid logical page # */
+#define VLAN_INVALID 0x48 /* Invalid Vlan ID */
+#define RDC_TAB_INVALID 0x49 /* Invalid RDC Group Number */
+#define LOCATION_INVALID 0x4a /* Invalid Entry Location */
+
+#define NPI_SUCCESS 0 /* Operation succeed */
+#define NPI_FAILURE 0x80000000 /* Operation failed */
+
+#define NPI_CNT_CLR_VAL 0
+
+/*
+ * Block identifier starts at bit 8.
+ */
+#define NPI_BLOCK_ID_SHIFT 8
+
+/*
+ * Port, channel and misc. information starts at bit 12.
+ */
+#define NPI_PORT_CHAN_SHIFT 12
+
+/*
+ * Software Block specific error codes start at 0x50.
+ */
+#define NPI_BK_ERROR_START 0x50
+
+/*
+ * Hardware block specific error codes start at 0x90.
+ */
+#define NPI_BK_HW_ER_START 0x90
+
+/* Structures for register tracing */
+
+typedef struct _rt_buf {
+ uint32_t ctl_addr;
+ uint32_t val_l32;
+ uint32_t val_h32;
+} rt_buf_t;
+
+/*
+ * Control Address field format
+ *
+ * Bit 0 - 23: Address
+ * Bit 24 - 25: Function Number
+ * Bit 26 - 29: Instance Number
+ * Bit 30: Read/Write Direction bit
+ * Bit 31: Invalid bit
+ */
+
+#define MAX_RTRACE_ENTRIES 1024
+#define MAX_RTRACE_IOC_ENTRIES 64
+#define TRACE_ADDR_MASK 0x00FFFFFF
+#define TRACE_FUNC_MASK 0x03000000
+#define TRACE_INST_MASK 0x3C000000
+#define TRACE_CTL_WR 0x40000000
+#define TRACE_CTL_INVALID 0x80000000
+#define TRACE_FUNC_SHIFT 24
+#define TRACE_INST_SHIFT 26
+#define MSG_BUF_SIZE 1024
+
+
+typedef struct _rtrace {
+ uint16_t next_idx;
+ uint16_t last_idx;
+ boolean_t wrapped;
+ rt_buf_t buf[MAX_RTRACE_ENTRIES];
+} rtrace_t;
+
+typedef struct _err_inject {
+ uint8_t blk_id;
+ uint8_t chan;
+ uint32_t err_id;
+ uint32_t control;
+} err_inject_t;
+
+/* Configuration options */
+typedef enum config_op {
+ DISABLE = 0,
+ ENABLE,
+ INIT
+} config_op_t;
+
+/* I/O options */
+typedef enum io_op {
+ OP_SET = 0,
+ OP_GET,
+ OP_UPDATE,
+ OP_CLEAR
+} io_op_t;
+
+/* Counter options */
+typedef enum counter_op {
+ SNAP_STICKY = 0,
+ SNAP_ACCUMULATE,
+ CLEAR
+} counter_op_t;
+
+/* NPI attribute */
+typedef struct _npi_attr_t {
+ uint32_t type;
+ uint32_t idata[16];
+ uint32_t odata[16];
+} npi_attr_t;
+
+/* NPI Handle */
+typedef struct _npi_handle_function {
+ uint16_t instance;
+ uint16_t function;
+} npi_handle_function_t;
+
+/* NPI Handle */
+typedef struct _npi_handle {
+ npi_reg_handle_t regh;
+ npi_reg_ptr_t regp;
+ boolean_t is_vraddr; /* virtualization region address */
+ npi_handle_function_t function;
+ void * nxgep;
+} npi_handle_t;
+
+/* NPI Counter */
+typedef struct _npi_counter_t {
+ uint32_t id;
+ char *name;
+ uint32_t val;
+} npi_counter_t;
+
+/*
+ * Commmon definitions for NPI RXDMA and TXDMA functions.
+ */
+typedef struct _dma_log_page {
+ uint8_t page_num;
+ boolean_t valid;
+ uint8_t func_num;
+ uint64_t mask;
+ uint64_t value;
+ uint64_t reloc;
+} dma_log_page_t, *p_dma_log_page_t;
+
+extern rtrace_t npi_rtracebuf;
+void npi_rtrace_buf_init(rtrace_t *);
+void npi_rtrace_update(npi_handle_t, boolean_t, rtrace_t *,
+ uint32_t, uint64_t);
+void npi_rtrace_buf_init(rtrace_t *);
+
+void npi_debug_msg(npi_handle_function_t, uint64_t,
+ char *, ...);
+
+#ifdef NPI_DEBUG
+#define NPI_DEBUG_MSG(params) npi_debug_msg params
+#else
+#define NPI_DEBUG_MSG(params)
+#endif
+
+#define NPI_ERROR_MSG(params) npi_debug_msg params
+#define NPI_REG_DUMP_MSG(params) npi_debug_msg params
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_espc.c b/usr/src/uts/sun4v/io/nxge/npi/npi_espc.c
new file mode 100644
index 0000000000..23919bd522
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_espc.c
@@ -0,0 +1,355 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_espc.h>
+#include <nxge_espc.h>
+
+npi_status_t
+npi_espc_pio_enable(npi_handle_t handle)
+{
+ NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_EN_REG), 0x1);
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_pio_disable(npi_handle_t handle)
+{
+ NXGE_REG_WR64(handle, ESPC_PIO_EN_REG, 0);
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_eeprom_entry(npi_handle_t handle, io_op_t op, uint32_t addr,
+ uint8_t *data)
+{
+ uint64_t val = 0;
+
+ if ((addr & ~EPC_EEPROM_ADDR_BITS) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_eerprom_entry"
+ " Invalid input addr <0x%x>\n",
+ addr));
+ return (NPI_FAILURE | NPI_ESPC_EEPROM_ADDR_INVALID);
+ }
+
+ if (op == OP_SET) {
+ val = EPC_WRITE_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT) |
+ *data;
+ NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
+ EPC_WAIT_RW_COMP(handle, &val, EPC_WRITE_COMPLETE);
+ if ((val & EPC_WRITE_COMPLETE) == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_eeprom_entry"
+ " HW Error: EEPROM_WR <0x%x>\n",
+ val));
+ return (NPI_FAILURE | NPI_ESPC_EEPROM_WRITE_FAILED);
+ }
+ } else if (op == OP_GET) {
+ val = EPC_READ_INITIATE | (addr << EPC_EEPROM_ADDR_SHIFT);
+ NXGE_REG_WR64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), val);
+ EPC_WAIT_RW_COMP(handle, &val, EPC_READ_COMPLETE);
+ if ((val & EPC_READ_COMPLETE) == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_eeprom_entry"
+ " HW Error: EEPROM_RD <0x%x>",
+ val));
+ return (NPI_FAILURE | NPI_ESPC_EEPROM_READ_FAILED);
+ }
+ NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG), &val);
+ *data = val & EPC_EEPROM_DATA_MASK;
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_eeprom_entry"
+ " Invalid Input addr <0x%x>\n", addr));
+ return (NPI_FAILURE | NPI_ESPC_OPCODE_INVALID);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_mac_addr_get(npi_handle_t handle, uint8_t *data)
+{
+ mac_addr_0_t mac0;
+ mac_addr_1_t mac1;
+
+ NXGE_REG_RD64(handle, ESPC_MAC_ADDR_0, &mac0.value);
+ data[0] = mac0.bits.w0.byte0;
+ data[1] = mac0.bits.w0.byte1;
+ data[2] = mac0.bits.w0.byte2;
+ data[3] = mac0.bits.w0.byte3;
+
+ NXGE_REG_RD64(handle, ESPC_MAC_ADDR_1, &mac1.value);
+ data[4] = mac1.bits.w0.byte4;
+ data[5] = mac1.bits.w0.byte5;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_num_ports_get(npi_handle_t handle, uint8_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
+ val &= NUM_PORTS_MASK;
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_num_macs_get(npi_handle_t handle, uint8_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_NUM_PORTS_MACS, &val);
+ val &= NUM_MAC_ADDRS_MASK;
+ val = (val >> NUM_MAC_ADDRS_SHIFT);
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_model_str_get(npi_handle_t handle, char *data)
+{
+ uint64_t val = 0;
+ uint16_t str_len;
+ int i, j;
+
+ NXGE_REG_RD64(handle, ESPC_MOD_STR_LEN, &val);
+ val &= MOD_STR_LEN_MASK;
+ str_len = (uint8_t)val;
+
+ if (str_len > MAX_MOD_STR_LEN) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_model_str_get"
+ " Model string length %d exceeds max %d\n",
+ str_len, MAX_MOD_STR_LEN));
+ return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
+ }
+
+ /*
+ * Might have to reverse the order depending on how the string
+ * is written.
+ */
+ for (i = 0, j = 0; i < str_len; j++) {
+ NXGE_REG_RD64(handle, ESPC_MOD_STR(j), &val);
+ data[i++] = ((char *)&val)[3];
+ data[i++] = ((char *)&val)[2];
+ data[i++] = ((char *)&val)[1];
+ data[i++] = ((char *)&val)[0];
+ }
+
+ data[str_len] = '\0';
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_bd_model_str_get(npi_handle_t handle, char *data)
+{
+ uint64_t val = 0;
+ uint16_t str_len;
+ int i, j;
+
+ NXGE_REG_RD64(handle, ESPC_BD_MOD_STR_LEN, &val);
+ val &= BD_MOD_STR_LEN_MASK;
+ str_len = (uint8_t)val;
+
+ if (str_len > MAX_BD_MOD_STR_LEN) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_model_str_get"
+ " Board Model string length %d "
+ "exceeds max %d\n",
+ str_len, MAX_BD_MOD_STR_LEN));
+ return (NPI_FAILURE | NPI_ESPC_STR_LEN_INVALID);
+ }
+
+ /*
+ * Might have to reverse the order depending on how the string
+ * is written.
+ */
+ for (i = 0, j = 0; i < str_len; j++) {
+ NXGE_REG_RD64(handle, ESPC_BD_MOD_STR(j), &val);
+ data[i++] = ((char *)&val)[3];
+ data[i++] = ((char *)&val)[2];
+ data[i++] = ((char *)&val)[1];
+ data[i++] = ((char *)&val)[0];
+ }
+
+ data[str_len] = '\0';
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_phy_type_get(npi_handle_t handle, uint8_t *data)
+{
+ phy_type_t phy;
+
+ NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
+ data[0] = phy.bits.w0.pt0_phy_type;
+ data[1] = phy.bits.w0.pt1_phy_type;
+ data[2] = phy.bits.w0.pt2_phy_type;
+ data[3] = phy.bits.w0.pt3_phy_type;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_port_phy_type_get(npi_handle_t handle, uint8_t *data, uint8_t portn)
+{
+ phy_type_t phy;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_port_phy_type_get"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_ESPC_PORT_INVALID);
+ }
+
+ NXGE_REG_RD64(handle, ESPC_PHY_TYPE, &phy.value);
+ switch (portn) {
+ case 0:
+ *data = phy.bits.w0.pt0_phy_type;
+ break;
+ case 1:
+ *data = phy.bits.w0.pt1_phy_type;
+ break;
+ case 2:
+ *data = phy.bits.w0.pt2_phy_type;
+ break;
+ case 3:
+ *data = phy.bits.w0.pt3_phy_type;
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_espc_port_phy_type_get"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_ESPC_PORT_INVALID);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_max_frame_get(npi_handle_t handle, uint16_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_MAX_FM_SZ, &val);
+ val &= MAX_FM_SZ_MASK;
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_version_get(npi_handle_t handle, uint16_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
+ val &= VER_NUM_MASK;
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_img_sz_get(npi_handle_t handle, uint16_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_VER_IMGSZ, &val);
+ val &= IMG_SZ_MASK;
+ val = val >> IMG_SZ_SHIFT;
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_chksum_get(npi_handle_t handle, uint8_t *data)
+{
+ uint64_t val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_CHKSUM, &val);
+ val &= CHKSUM_MASK;
+ *data = (uint8_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_espc_intr_num_get(npi_handle_t handle, uint8_t *data)
+{
+ intr_num_t intr;
+
+ NXGE_REG_RD64(handle, ESPC_INTR_NUM, &intr.value);
+ data[0] = intr.bits.w0.pt0_intr_num;
+ data[1] = intr.bits.w0.pt1_intr_num;
+ data[2] = intr.bits.w0.pt2_intr_num;
+ data[3] = intr.bits.w0.pt3_intr_num;
+
+ return (NPI_SUCCESS);
+}
+
+void
+npi_espc_dump(npi_handle_t handle)
+{
+ int i;
+ uint64_t val = 0;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "Dumping SEEPROM registers directly:\n\n"));
+
+ for (i = 0; i < 23; i++) {
+ NXGE_REG_RD64(handle, ESPC_NCR_REGN(i), &val);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "reg[%d] 0x%llx\n",
+ i, val & 0xffffffff));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n\n"));
+}
+
+uint32_t
+npi_espc_reg_get(npi_handle_t handle, int reg_idx)
+{
+ uint64_t val = 0;
+ uint32_t reg_val = 0;
+
+ NXGE_REG_RD64(handle, ESPC_NCR_REGN(reg_idx), &val);
+ reg_val = val & 0xffffffff;
+
+ return (reg_val);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_espc.h b/usr/src/uts/sun4v/io/nxge/npi/npi_espc.h
new file mode 100644
index 0000000000..867344b2da
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_espc.h
@@ -0,0 +1,87 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_ESPC_H
+#define _NPI_ESPC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_espc_hw.h>
+
+#define EPC_WAIT_RW_COMP(handle, val_p, comp_bit) {\
+ uint32_t cnt = MAX_PIO_RETRIES;\
+ do {\
+ NXGE_DELAY(EPC_RW_WAIT);\
+ NXGE_REG_RD64(handle, ESPC_REG_ADDR(ESPC_PIO_STATUS_REG),\
+ val_p); cnt--;\
+ } while (((val & comp_bit) == 0) && (cnt > 0));\
+}
+
+/* ESPC specific errors */
+
+#define ESPC_EEPROM_ADDR_INVALID 0x51
+#define ESPC_STR_LEN_INVALID 0x91
+
+/* ESPC error return macros */
+
+#define NPI_ESPC_EEPROM_ADDR_INVALID ((ESPC_BLK_ID << 8) |\
+ ESPC_EEPROM_ADDR_INVALID)
+#define NPI_ESPC_EEPROM_WRITE_FAILED ((ESPC_BLK_ID << 8) | WRITE_FAILED)
+#define NPI_ESPC_EEPROM_READ_FAILED ((ESPC_BLK_ID << 8) | READ_FAILED)
+#define NPI_ESPC_OPCODE_INVALID ((ESPC_BLK_ID << 8) | OPCODE_INVALID)
+#define NPI_ESPC_STR_LEN_INVALID ((ESPC_BLK_ID << 8) |\
+ ESPC_STR_LEN_INVALID)
+#define NPI_ESPC_PORT_INVALID ((ESPC_BLK_ID << 8) | PORT_INVALID)
+
+npi_status_t npi_espc_pio_enable(npi_handle_t);
+npi_status_t npi_espc_pio_disable(npi_handle_t);
+npi_status_t npi_espc_eeprom_entry(npi_handle_t, io_op_t,
+ uint32_t, uint8_t *);
+npi_status_t npi_espc_mac_addr_get(npi_handle_t, uint8_t *);
+npi_status_t npi_espc_num_ports_get(npi_handle_t, uint8_t *);
+ npi_status_t npi_espc_num_macs_get(npi_handle_t, uint8_t *);
+npi_status_t npi_espc_model_str_get(npi_handle_t, char *);
+npi_status_t npi_espc_bd_model_str_get(npi_handle_t, char *);
+npi_status_t npi_espc_phy_type_get(npi_handle_t, uint8_t *);
+npi_status_t npi_espc_port_phy_type_get(npi_handle_t, uint8_t *,
+ uint8_t);
+npi_status_t npi_espc_max_frame_get(npi_handle_t, uint16_t *);
+npi_status_t npi_espc_version_get(npi_handle_t, uint16_t *);
+ npi_status_t npi_espc_img_sz_get(npi_handle_t, uint16_t *);
+npi_status_t npi_espc_chksum_get(npi_handle_t, uint8_t *);
+npi_status_t npi_espc_intr_num_get(npi_handle_t, uint8_t *);
+uint32_t npi_espc_reg_get(npi_handle_t, int);
+void npi_espc_dump(npi_handle_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_ESPC_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.c b/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.c
new file mode 100644
index 0000000000..50e16d0a52
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.c
@@ -0,0 +1,2976 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_fflp.h>
+#include <nxge_common.h>
+
+/* macros to compute calss configuration register offset */
+
+#define GET_TCAM_CLASS_OFFSET(cls) \
+ (FFLP_TCAM_CLS_BASE_OFFSET + (cls - 2) * 8)
+#define GET_TCAM_KEY_OFFSET(cls) \
+ (FFLP_TCAM_KEY_BASE_OFFSET + (cls - 4) * 8)
+#define GET_FLOW_KEY_OFFSET(cls) \
+ (FFLP_FLOW_KEY_BASE_OFFSET + (cls - 4) * 8)
+
+#define HASHTBL_PART_REG_STEP 8192
+#define HASHTBL_PART_REG_VIR_OFFSET 0x2100
+#define HASHTBL_PART_REG_VIR_STEP 0x4000
+#define GET_HASHTBL_PART_OFFSET_NVIR(partid, reg) \
+ ((partid * HASHTBL_PART_REG_STEP) + reg)
+
+#define GET_HASHTBL_PART_OFFSET(handle, partid, reg) \
+ (handle.is_vraddr ? \
+ (((partid & 0x1) * HASHTBL_PART_REG_VIR_STEP) + \
+ (reg & 0x8) + (HASHTBL_PART_REG_VIR_OFFSET)) : \
+ (partid * HASHTBL_PART_REG_STEP) + reg)
+
+#define FFLP_PART_OFFSET(partid, reg) ((partid * 8) + reg)
+#define FFLP_VLAN_OFFSET(vid, reg) ((vid * 8) + reg)
+
+#define TCAM_COMPLETION_TRY_COUNT 10
+#define BIT_ENABLE 0x1
+#define BIT_DISABLE 0x0
+
+#define FCRAM_PARTITION_VALID(partid) \
+ ((partid < NXGE_MAX_RDC_GRPS))
+#define FFLP_VLAN_VALID(vid) \
+ ((vid > 0) && (vid < NXGE_MAX_VLANS))
+#define FFLP_PORT_VALID(port) \
+ ((port < MAX_PORTS_PER_NXGE))
+#define FFLP_RDC_TABLE_VALID(table) \
+ ((table < NXGE_MAX_RDC_GRPS))
+#define TCAM_L3_USR_CLASS_VALID(class) \
+ ((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_IP_USER_7))
+#define TCAM_L2_USR_CLASS_VALID(class) \
+ ((class == TCAM_CLASS_ETYPE_1) || (class == TCAM_CLASS_ETYPE_2))
+#define TCAM_L3_CLASS_VALID(class) \
+ ((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_SCTP_IPV6))
+#define TCAM_CLASS_VALID(class) \
+ ((class >= TCAM_CLASS_ETYPE_1) && (class <= TCAM_CLASS_RARP))
+
+
+uint64_t fflp_fzc_offset[] = {
+ FFLP_ENET_VLAN_TBL_REG, FFLP_L2_CLS_ENET1_REG, FFLP_L2_CLS_ENET2_REG,
+ FFLP_TCAM_KEY_IP_USR4_REG, FFLP_TCAM_KEY_IP_USR5_REG,
+ FFLP_TCAM_KEY_IP_USR6_REG, FFLP_TCAM_KEY_IP_USR7_REG,
+ FFLP_TCAM_KEY_IP4_TCP_REG, FFLP_TCAM_KEY_IP4_UDP_REG,
+ FFLP_TCAM_KEY_IP4_AH_ESP_REG, FFLP_TCAM_KEY_IP4_SCTP_REG,
+ FFLP_TCAM_KEY_IP6_TCP_REG, FFLP_TCAM_KEY_IP6_UDP_REG,
+ FFLP_TCAM_KEY_IP6_AH_ESP_REG, FFLP_TCAM_KEY_IP6_SCTP_REG,
+ FFLP_TCAM_KEY_0_REG, FFLP_TCAM_KEY_1_REG, FFLP_TCAM_KEY_2_REG,
+ FFLP_TCAM_KEY_3_REG, FFLP_TCAM_MASK_0_REG, FFLP_TCAM_MASK_1_REG,
+ FFLP_TCAM_MASK_2_REG, FFLP_TCAM_MASK_3_REG, FFLP_TCAM_CTL_REG,
+ FFLP_VLAN_PAR_ERR_REG, FFLP_TCAM_ERR_REG, HASH_LKUP_ERR_LOG1_REG,
+ HASH_LKUP_ERR_LOG2_REG, FFLP_FCRAM_ERR_TST0_REG,
+ FFLP_FCRAM_ERR_TST1_REG, FFLP_FCRAM_ERR_TST2_REG, FFLP_ERR_MSK_REG,
+ FFLP_CFG_1_REG, FFLP_DBG_TRAIN_VCT_REG, FFLP_TCP_CFLAG_MSK_REG,
+ FFLP_FCRAM_REF_TMR_REG, FFLP_FLOW_KEY_IP_USR4_REG,
+ FFLP_FLOW_KEY_IP_USR5_REG, FFLP_FLOW_KEY_IP_USR6_REG,
+ FFLP_FLOW_KEY_IP_USR7_REG, FFLP_FLOW_KEY_IP4_TCP_REG,
+ FFLP_FLOW_KEY_IP4_UDP_REG, FFLP_FLOW_KEY_IP4_AH_ESP_REG,
+ FFLP_FLOW_KEY_IP4_SCTP_REG, FFLP_FLOW_KEY_IP6_TCP_REG,
+ FFLP_FLOW_KEY_IP6_UDP_REG, FFLP_FLOW_KEY_IP6_AH_ESP_REG,
+ FFLP_FLOW_KEY_IP6_SCTP_REG, FFLP_H1POLY_REG, FFLP_H2POLY_REG,
+ FFLP_FLW_PRT_SEL_REG
+};
+
+const char *fflp_fzc_name[] = {
+ "FFLP_ENET_VLAN_TBL_REG", "FFLP_L2_CLS_ENET1_REG",
+ "FFLP_L2_CLS_ENET2_REG", "FFLP_TCAM_KEY_IP_USR4_REG",
+ "FFLP_TCAM_KEY_IP_USR5_REG", "FFLP_TCAM_KEY_IP_USR6_REG",
+ "FFLP_TCAM_KEY_IP_USR7_REG", "FFLP_TCAM_KEY_IP4_TCP_REG",
+ "FFLP_TCAM_KEY_IP4_UDP_REG", "FFLP_TCAM_KEY_IP4_AH_ESP_REG",
+ "FFLP_TCAM_KEY_IP4_SCTP_REG", "FFLP_TCAM_KEY_IP6_TCP_REG",
+ "FFLP_TCAM_KEY_IP6_UDP_REG", "FFLP_TCAM_KEY_IP6_AH_ESP_REG",
+ "FFLP_TCAM_KEY_IP6_SCTP_REG", "FFLP_TCAM_KEY_0_REG",
+ "FFLP_TCAM_KEY_1_REG", "FFLP_TCAM_KEY_2_REG", "FFLP_TCAM_KEY_3_REG",
+ "FFLP_TCAM_MASK_0_REG", "FFLP_TCAM_MASK_1_REG", "FFLP_TCAM_MASK_2_REG",
+ "FFLP_TCAM_MASK_3_REG", "FFLP_TCAM_CTL_REG", "FFLP_VLAN_PAR_ERR_REG",
+ "FFLP_TCAM_ERR_REG", "HASH_LKUP_ERR_LOG1_REG",
+ "HASH_LKUP_ERR_LOG2_REG", "FFLP_FCRAM_ERR_TST0_REG",
+ "FFLP_FCRAM_ERR_TST1_REG", "FFLP_FCRAM_ERR_TST2_REG",
+ "FFLP_ERR_MSK_REG", "FFLP_CFG_1_REG", "FFLP_DBG_TRAIN_VCT_REG",
+ "FFLP_TCP_CFLAG_MSK_REG", "FFLP_FCRAM_REF_TMR_REG",
+ "FFLP_FLOW_KEY_IP_USR4_REG", "FFLP_FLOW_KEY_IP_USR5_REG",
+ "FFLP_FLOW_KEY_IP_USR6_REG", "FFLP_FLOW_KEY_IP_USR7_REG",
+ "FFLP_FLOW_KEY_IP4_TCP_REG", "FFLP_FLOW_KEY_IP4_UDP_REG",
+ "FFLP_FLOW_KEY_IP4_AH_ESP_REG", "FFLP_FLOW_KEY_IP4_SCTP_REG",
+ "FFLP_FLOW_KEY_IP6_TCP_REG", "FFLP_FLOW_KEY_IP6_UDP_REG",
+ "FFLP_FLOW_KEY_IP6_AH_ESP_REG",
+ "FFLP_FLOW_KEY_IP6_SCTP_REG", "FFLP_H1POLY_REG", "FFLP_H2POLY_REG",
+ "FFLP_FLW_PRT_SEL_REG"
+};
+
+uint64_t fflp_reg_offset[] = {
+ FFLP_HASH_TBL_ADDR_REG, FFLP_HASH_TBL_DATA_REG,
+ FFLP_HASH_TBL_DATA_LOG_REG
+};
+
+const char *fflp_reg_name[] = {
+ "FFLP_HASH_TBL_ADDR_REG", "FFLP_HASH_TBL_DATA_REG",
+ "FFLP_HASH_TBL_DATA_LOG_REG"
+};
+
+
+
+
+npi_status_t
+npi_fflp_dump_regs(npi_handle_t handle)
+{
+
+ uint64_t value;
+ int num_regs, i;
+
+ num_regs = sizeof (fflp_fzc_offset) / sizeof (uint64_t);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nFFLP_FZC Register Dump \n"));
+ for (i = 0; i < num_regs; i++) {
+ REG_PIO_READ64(handle, fflp_fzc_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ " %8llx %s\t %8llx \n",
+ fflp_fzc_offset[i], fflp_fzc_name[i], value));
+
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nFFLP Register Dump\n"));
+ num_regs = sizeof (fflp_reg_offset) / sizeof (uint64_t);
+
+ for (i = 0; i < num_regs; i++) {
+ REG_PIO_READ64(handle, fflp_reg_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ " %8llx %s\t %8llx \n",
+ fflp_reg_offset[i], fflp_reg_name[i], value));
+
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FFLP Register Dump done\n"));
+
+ return (NPI_SUCCESS);
+}
+
+void
+npi_fflp_vlan_tbl_dump(npi_handle_t handle)
+{
+ uint64_t offset;
+ vlan_id_t vlan_id;
+ uint64_t value;
+ vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nVlan Table Dump \n"));
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "VID\t Offset\t Value\n"));
+
+ for (vlan_id = start; vlan_id < stop; vlan_id++) {
+ offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
+ REG_PIO_READ64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "%x\t %llx\t %llx\n", vlan_id, offset, value));
+ }
+
+}
+
+
+
+static uint64_t
+npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type);
+
+
+/*
+ * npi_fflp_tcam_check_completion()
+ * Returns TCAM completion status.
+ *
+ * Input:
+ * op_type : Read, Write, Compare
+ * handle : OS specific handle
+ *
+ * Output:
+ * For Read and write operations:
+ * 0 Successful
+ * -1 Fail/timeout
+ *
+ * For Compare operations (debug only )
+ * TCAM_REG_CTL read value on success
+ * value contains match location
+ * NPI_TCAM_COMP_NO_MATCH no match
+ *
+ */
+
+
+static uint64_t
+npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type)
+{
+
+ uint32_t try_counter, tcam_delay = 10;
+ tcam_ctl_t tctl;
+
+ try_counter = TCAM_COMPLETION_TRY_COUNT;
+
+ switch (op_type) {
+ case TCAM_RWC_STAT:
+
+ READ_TCAM_REG_CTL(handle, &tctl.value);
+ while ((try_counter) &&
+ (tctl.bits.ldw.stat != TCAM_CTL_RWC_RWC_STAT)) {
+ try_counter--;
+ NXGE_DELAY(tcam_delay);
+ READ_TCAM_REG_CTL(handle, &tctl.value);
+ }
+
+ if (!try_counter) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " TCAM RWC_STAT operation"
+ " failed to complete \n"));
+ return (NPI_FFLP_TCAM_HW_ERROR);
+ }
+
+ tctl.value = 0;
+ break;
+
+ case TCAM_RWC_MATCH:
+ READ_TCAM_REG_CTL(handle, &tctl.value);
+
+ while ((try_counter) &&
+ (tctl.bits.ldw.match != TCAM_CTL_RWC_RWC_MATCH)) {
+ try_counter--;
+ NXGE_DELAY(tcam_delay);
+ READ_TCAM_REG_CTL(handle, &tctl.value);
+ }
+
+ if (!try_counter) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " TCAM Match operation"
+ "failed to find match \n"));
+ tctl.value = NPI_TCAM_COMP_NO_MATCH;
+ }
+
+
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " Invalid TCAM completion Request \n"));
+ return (NPI_FFLP_ERROR |
+ NPI_TCAM_ERROR | OPCODE_INVALID);
+ }
+
+ return (tctl.value);
+}
+
+
+
+
+
+/*
+ * npi_fflp_tcam_entry_invalidate()
+ *
+ * invalidates entry at tcam location
+ *
+ * Input
+ * location
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_tcam_entry_invalidate(npi_handle_t handle, tcam_location_t location)
+{
+
+ tcam_ctl_t tctl, tctl_stat;
+
+/*
+ * Need to write zero to class field.
+ * Class field is bits [195:191].
+ * This corresponds to TCAM key 0 register
+ *
+ */
+
+
+ WRITE_TCAM_REG_MASK0(handle, 0xffULL);
+ WRITE_TCAM_REG_KEY0(handle, 0x0ULL);
+ tctl.value = 0;
+ tctl.bits.ldw.location = location;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
+
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+
+ tctl_stat.value = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+
+ if (tctl_stat.value & NPI_FAILURE)
+ return (NPI_FFLP_TCAM_HW_ERROR);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+/*
+ * npi_fflp_tcam_entry_match()
+ *
+ * lookup a tcam entry in the TCAM
+ *
+ * Input
+ * tcam_ptr TCAM entry ptr
+ *
+ * Return
+ *
+ * NPI_FAILURE | NPI_XX_ERROR: Operational Error (HW etc ...)
+ * NPI_TCAM_NO_MATCH: no match
+ * 0 - TCAM_SIZE: matching entry location (if match)
+ */
+
+int
+npi_fflp_tcam_entry_match(npi_handle_t handle, tcam_entry_t *tcam_ptr)
+{
+
+ uint64_t tcam_stat = 0;
+ tcam_ctl_t tctl, tctl_stat;
+
+ WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
+ WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
+ WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
+ WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
+
+ WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
+ WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
+ WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
+ WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
+
+ tctl.value = 0;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_CMP;
+
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+
+ tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+ if (tcam_stat & NPI_FAILURE) {
+ return ((uint32_t)tcam_stat);
+ }
+
+ tctl_stat.value = npi_fflp_tcam_check_completion(handle,
+ TCAM_RWC_MATCH);
+
+ if (tctl_stat.bits.ldw.match == TCAM_CTL_RWC_RWC_MATCH) {
+ return (uint32_t)(tctl_stat.bits.ldw.location);
+ }
+
+ return ((uint32_t)tctl_stat.value);
+
+}
+
+
+
+/*
+ * npi_fflp_tcam_entry_read ()
+ *
+ * Reads a tcam entry from the TCAM location, location
+ *
+ * Input:
+ * location
+ * tcam_ptr
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+
+npi_status_t
+npi_fflp_tcam_entry_read(npi_handle_t handle,
+ tcam_location_t location,
+ struct tcam_entry *tcam_ptr)
+{
+
+ uint64_t tcam_stat;
+ tcam_ctl_t tctl;
+
+ tctl.value = 0;
+ tctl.bits.ldw.location = location;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_RD;
+
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+
+ tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+
+ if (tcam_stat & NPI_FAILURE) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "TCAM read failed loc %d \n", location));
+ return (NPI_FFLP_TCAM_RD_ERROR);
+ }
+
+ READ_TCAM_REG_MASK0(handle, &tcam_ptr->mask0);
+ READ_TCAM_REG_MASK1(handle, &tcam_ptr->mask1);
+ READ_TCAM_REG_MASK2(handle, &tcam_ptr->mask2);
+ READ_TCAM_REG_MASK3(handle, &tcam_ptr->mask3);
+
+ READ_TCAM_REG_KEY0(handle, &tcam_ptr->key0);
+ READ_TCAM_REG_KEY1(handle, &tcam_ptr->key1);
+ READ_TCAM_REG_KEY2(handle, &tcam_ptr->key2);
+ READ_TCAM_REG_KEY3(handle, &tcam_ptr->key3);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_tcam_entry_write()
+ *
+ * writes a tcam entry to the TCAM location, location
+ *
+ * Input:
+ * location
+ * tcam_ptr
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+npi_status_t
+npi_fflp_tcam_entry_write(npi_handle_t handle,
+ tcam_location_t location,
+ tcam_entry_t *tcam_ptr)
+{
+
+ uint64_t tcam_stat;
+
+ tcam_ctl_t tctl;
+
+ WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
+ WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
+ WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
+ WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
+
+ WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
+ WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
+ WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
+ WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
+
+ NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
+ " tcam write: location %x\n"
+ " key: %llx %llx %llx %llx \n"
+ " mask: %llx %llx %llx %llx \n",
+ location, tcam_ptr->key0, tcam_ptr->key1,
+ tcam_ptr->key2, tcam_ptr->key3,
+ tcam_ptr->mask0, tcam_ptr->mask1,
+ tcam_ptr->mask2, tcam_ptr->mask3));
+ tctl.value = 0;
+ tctl.bits.ldw.location = location;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
+ NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
+ " tcam write: ctl value %llx \n", tctl.value));
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+
+ tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+
+ if (tcam_stat & NPI_FAILURE) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "TCAM Write failed loc %d \n", location));
+ return (NPI_FFLP_TCAM_WR_ERROR);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_tcam_asc_ram_entry_write()
+ *
+ * writes a tcam associatedRAM at the TCAM location, location
+ *
+ * Input:
+ * location tcam associatedRAM location
+ * ram_data Value to write
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_tcam_asc_ram_entry_write(npi_handle_t handle,
+ tcam_location_t location,
+ uint64_t ram_data)
+{
+
+ uint64_t tcam_stat = 0;
+ tcam_ctl_t tctl;
+
+
+ WRITE_TCAM_REG_KEY1(handle, ram_data);
+
+ tctl.value = 0;
+ tctl.bits.ldw.location = location;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_WR;
+
+ NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
+ " tcam ascr write: location %x data %llx ctl value %llx \n",
+ location, ram_data, tctl.value));
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+ tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+
+ if (tcam_stat & NPI_FAILURE) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "TCAM RAM write failed loc %d \n", location));
+ return (NPI_FFLP_ASC_RAM_WR_ERROR);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+
+
+/*
+ * npi_fflp_tcam_asc_ram_entry_read()
+ *
+ * reads a tcam associatedRAM content at the TCAM location, location
+ *
+ * Input:
+ * location tcam associatedRAM location
+ * ram_data ptr to return contents
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_tcam_asc_ram_entry_read(npi_handle_t handle,
+ tcam_location_t location,
+ uint64_t *ram_data)
+{
+
+ uint64_t tcam_stat;
+ tcam_ctl_t tctl;
+
+
+ tctl.value = 0;
+ tctl.bits.ldw.location = location;
+ tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_RD;
+
+ WRITE_TCAM_REG_CTL(handle, tctl.value);
+
+ tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
+
+ if (tcam_stat & NPI_FAILURE) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "TCAM RAM read failed loc %d \n", location));
+ return (NPI_FFLP_ASC_RAM_RD_ERROR);
+ }
+
+ READ_TCAM_REG_KEY1(handle, ram_data);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/* FFLP FCRAM Related functions */
+/* The following are FCRAM datapath functions */
+
+/*
+ * npi_fflp_fcram_entry_write ()
+ * Populates an FCRAM entry
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: Index to the FCRAM.
+ * Corresponds to last 20 bits of H1 value
+ * fcram_ptr: Pointer to the FCRAM contents to be used for writing
+ * format: Entry Format. Determines the size of the write.
+ * FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit write)
+ * FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit write)
+ * FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit write)
+ *
+ * Outputs:
+ * NPI_SUCCESS: Successful
+ * NPI_FAILURE | NPI_XX_ERROR failure and reason
+ */
+
+npi_status_t
+npi_fflp_fcram_entry_write(npi_handle_t handle, part_id_t partid,
+ uint32_t location, fcram_entry_t *fcram_ptr,
+ fcram_entry_format_t format)
+
+{
+
+ int num_subareas = 0;
+ uint64_t addr_reg, data_reg;
+ int subarea;
+ int autoinc;
+ hash_tbl_addr_t addr;
+ switch (format) {
+ case FCRAM_ENTRY_OPTIM:
+ if (location % 8) {
+ /* need to be 8 byte alligned */
+
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_OOPTIM Write:"
+ " unaligned location %llx \n",
+ location));
+
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+
+ num_subareas = 1;
+ autoinc = 0;
+ break;
+
+ case FCRAM_ENTRY_EX_IP4:
+ if (location % 32) {
+/* need to be 32 byte alligned */
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_EX_IP4 Write:"
+ " unaligned location %llx \n",
+ location));
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+
+ num_subareas = 4;
+ autoinc = 1;
+
+ break;
+ case FCRAM_ENTRY_EX_IP6:
+ if (location % 64) {
+ /* need to be 64 byte alligned */
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_EX_IP6 Write:"
+ " unaligned location %llx \n",
+ location));
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+
+ }
+ num_subareas = 7;
+ autoinc = 1;
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_entry_write:"
+ " unknown format param location %llx\n",
+ location));
+ return (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | OPCODE_INVALID);
+ }
+
+ addr.value = 0;
+ addr.bits.ldw.autoinc = autoinc;
+ addr.bits.ldw.addr = location;
+ addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_ADDR_REG);
+ data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_DATA_REG);
+/* write to addr reg */
+ REG_PIO_WRITE64(handle, addr_reg, addr.value);
+/* write data to the data register */
+
+ for (subarea = 0; subarea < num_subareas; subarea++) {
+ REG_PIO_WRITE64(handle, data_reg, fcram_ptr->value[subarea]);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fflp_fcram_read_read ()
+ * Reads an FCRAM entry
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: Index to the FCRAM.
+ * Corresponds to last 20 bits of H1 value
+ *
+ * fcram_ptr: Pointer to the FCRAM contents to be updated
+ * format: Entry Format. Determines the size of the read.
+ * FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit read)
+ * FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit read )
+ * FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit read )
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_fcram_entry_read(npi_handle_t handle, part_id_t partid,
+ uint32_t location, fcram_entry_t *fcram_ptr,
+ fcram_entry_format_t format)
+{
+
+ int num_subareas = 0;
+ uint64_t addr_reg, data_reg;
+ int subarea, autoinc;
+ hash_tbl_addr_t addr;
+ switch (format) {
+ case FCRAM_ENTRY_OPTIM:
+ if (location % 8) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_OOPTIM Read:"
+ " unaligned location %llx \n",
+ location));
+ /* need to be 8 byte alligned */
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+ num_subareas = 1;
+ autoinc = 0;
+ break;
+ case FCRAM_ENTRY_EX_IP4:
+ if (location % 32) {
+ /* need to be 32 byte alligned */
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_EX_IP4 READ:"
+ " unaligned location %llx \n",
+ location));
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+ num_subareas = 4;
+ autoinc = 1;
+
+ break;
+ case FCRAM_ENTRY_EX_IP6:
+ if (location % 64) {
+ /* need to be 64 byte alligned */
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_EX_IP6 READ:"
+ " unaligned location %llx \n",
+ location));
+
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+ num_subareas = 7;
+ autoinc = 1;
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_entry_read:"
+ " unknown format param location %llx\n",
+ location));
+ return (NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+ addr.value = 0;
+ addr.bits.ldw.autoinc = autoinc;
+ addr.bits.ldw.addr = location;
+ addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_ADDR_REG);
+ data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_DATA_REG);
+/* write to addr reg */
+ REG_PIO_WRITE64(handle, addr_reg, addr.value);
+/* read data from the data register */
+ for (subarea = 0; subarea < num_subareas; subarea++) {
+ REG_PIO_READ64(handle, data_reg, &fcram_ptr->value[subarea]);
+ }
+
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_fcram_entry_invalidate ()
+ * Invalidate FCRAM entry at the given location
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the FCRAM/hash entry.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_entry_invalidate(npi_handle_t handle, part_id_t partid,
+ uint32_t location)
+{
+
+ hash_tbl_addr_t addr;
+ uint64_t addr_reg, data_reg;
+ hash_hdr_t hdr;
+
+
+ if (location % 8) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " FCRAM_ENTRY_Invalidate:"
+ " unaligned location %llx \n",
+ location));
+ /* need to be 8 byte alligned */
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+
+ addr.value = 0;
+ addr.bits.ldw.addr = location;
+ addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_ADDR_REG);
+ data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_DATA_REG);
+
+/* write to addr reg */
+ REG_PIO_WRITE64(handle, addr_reg, addr.value);
+
+ REG_PIO_READ64(handle, data_reg, &hdr.value);
+ hdr.exact_hdr.valid = 0;
+ REG_PIO_WRITE64(handle, data_reg, hdr.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+/*
+ * npi_fflp_fcram_write_subarea ()
+ * Writes to FCRAM entry subarea i.e the 8 bytes within the 64 bytes
+ * pointed by the last 20 bits of H1. Effectively, this accesses
+ * specific 8 bytes within the hash table bucket.
+ *
+ * H1--> |-----------------|
+ * | subarea 0 |
+ * |_________________|
+ * | Subarea 1 |
+ * |_________________|
+ * | ....... |
+ * |_________________|
+ * | Subarea 7 |
+ * |_________________|
+ *
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the subarea. It is derived from:
+ * Bucket = [19:15][14:0] (20 bits of H1)
+ * location = (Bucket << 3 ) + subarea * 8
+ * = [22:18][17:3] || subarea * 8
+ * data: Data
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_subarea_write(npi_handle_t handle, part_id_t partid,
+ uint32_t location, uint64_t data)
+{
+
+ hash_tbl_addr_t addr;
+ uint64_t addr_reg, data_reg;
+
+
+ if (location % 8) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_subarea_write:"
+ " unaligned location %llx \n",
+ location));
+ /* need to be 8 byte alligned */
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+
+ addr.value = 0;
+ addr.bits.ldw.addr = location;
+ addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_ADDR_REG);
+ data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_DATA_REG);
+
+/* write to addr reg */
+ REG_PIO_WRITE64(handle, addr_reg, addr.value);
+ REG_PIO_WRITE64(handle, data_reg, data);
+
+ return (NPI_SUCCESS);
+
+}
+
+/*
+ * npi_fflp_fcram_subarea_read ()
+ * Reads an FCRAM entry subarea i.e the 8 bytes within the 64 bytes
+ * pointed by the last 20 bits of H1. Effectively, this accesses
+ * specific 8 bytes within the hash table bucket.
+ *
+ * H1--> |-----------------|
+ * | subarea 0 |
+ * |_________________|
+ * | Subarea 1 |
+ * |_________________|
+ * | ....... |
+ * |_________________|
+ * | Subarea 7 |
+ * |_________________|
+ *
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the subarea. It is derived from:
+ * Bucket = [19:15][14:0] (20 bits of H1)
+ * location = (Bucket << 3 ) + subarea * 8
+ * = [22:18][17:3] || subarea * 8
+ * data: ptr do write subarea contents to.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_subarea_read(npi_handle_t handle, part_id_t partid,
+ uint32_t location, uint64_t *data)
+
+{
+
+ hash_tbl_addr_t addr;
+ uint64_t addr_reg, data_reg;
+
+ if (location % 8) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_subarea_read:"
+ " unaligned location %llx \n",
+ location));
+ /* need to be 8 byte alligned */
+ return (NPI_FFLP_FCRAM_LOC_INVALID);
+ }
+
+ addr.value = 0;
+ addr.bits.ldw.addr = location;
+ addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_ADDR_REG);
+ data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
+ FFLP_HASH_TBL_DATA_REG);
+
+/* write to addr reg */
+ REG_PIO_WRITE64(handle, addr_reg, addr.value);
+ REG_PIO_READ64(handle, data_reg, data);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * The following are zero function fflp configuration functions.
+ */
+
+/*
+ * npi_fflp_fcram_config_partition()
+ * Partitions and configures the FCRAM
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ * part_size Size of the partition
+ *
+ * Return
+ * 0 Successful
+ * Non zero error code Partition failed, and reason.
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_fcram_partition(npi_handle_t handle, part_id_t partid,
+ uint8_t base_mask, uint8_t base_reloc)
+
+{
+/*
+ * assumes that the base mask and relocation are computed somewhere
+ * and kept in the state data structure. Alternativiely, one can pass
+ * a partition size and a starting address and this routine can compute
+ * the mask and reloc vlaues.
+ */
+
+ flow_prt_sel_t sel;
+ uint64_t offset;
+ if (!FCRAM_PARTITION_VALID(partid)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_fcram_partition:"
+ " Invalid Partition %d \n",
+ partid));
+ return (NPI_FFLP_FCRAM_PART_INVALID);
+ }
+
+ offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
+ sel.value = 0;
+ sel.bits.ldw.mask = base_mask;
+ sel.bits.ldw.base = base_reloc;
+ sel.bits.ldw.ext = BIT_DISABLE; /* disable */
+ REG_PIO_WRITE64(handle, offset, sel.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_fcram_partition_enable
+ * Enable previously configured FCRAM partition
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ *
+ * Return
+ * 0 Successful
+ * Non zero error code Enable failed, and reason.
+ *
+ */
+npi_status_t
+npi_fflp_cfg_fcram_partition_enable (npi_handle_t handle, part_id_t partid)
+
+{
+
+ flow_prt_sel_t sel;
+ uint64_t offset;
+
+
+ if (!FCRAM_PARTITION_VALID(partid)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_partition enable:"
+ " Invalid Partition %d \n",
+ partid));
+ return (NPI_FFLP_FCRAM_PART_INVALID);
+ }
+
+ offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
+
+ REG_PIO_READ64(handle, offset, &sel.value);
+ sel.bits.ldw.ext = BIT_ENABLE; /* enable */
+ REG_PIO_WRITE64(handle, offset, sel.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_fcram_partition_disable
+ * Disabled previously configured FCRAM partition
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t
+npi_fflp_cfg_fcram_partition_disable(npi_handle_t handle, part_id_t partid)
+
+{
+
+ flow_prt_sel_t sel;
+ uint64_t offset;
+
+ if (!FCRAM_PARTITION_VALID(partid)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_partition disable:"
+ " Invalid Partition %d \n",
+ partid));
+ return (NPI_FFLP_FCRAM_PART_INVALID);
+ }
+ offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
+ REG_PIO_READ64(handle, offset, &sel.value);
+ sel.bits.ldw.ext = BIT_DISABLE; /* disable */
+ REG_PIO_WRITE64(handle, offset, sel.value);
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fflp_cam_errorcheck_disable
+ * Disables FCRAM and TCAM error checking
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t
+npi_fflp_cfg_cam_errorcheck_disable(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+
+ fflp_cfg.bits.ldw.errordis = BIT_ENABLE;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_fflp_cam_errorcheck_enable
+ * Enables FCRAM and TCAM error checking
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t
+npi_fflp_cfg_cam_errorcheck_enable(npi_handle_t handle)
+
+{
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+
+ fflp_cfg.bits.ldw.errordis = BIT_DISABLE;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+/*
+ * npi_fflp_cam_llcsnap_enable
+ * Enables input parser llcsnap recognition
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t
+npi_fflp_cfg_llcsnap_enable(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+
+ fflp_cfg.bits.ldw.llcsnap = BIT_ENABLE;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_cam_llcsnap_disable
+ * Disables input parser llcsnap recognition
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_llcsnap_disable(npi_handle_t handle)
+
+{
+
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+
+ fflp_cfg.bits.ldw.llcsnap = BIT_DISABLE;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_config_fcram_refresh
+ * Set FCRAM min and max refresh time.
+ *
+ * Input
+ * min_time Minimum Refresh time count
+ * max_time maximum Refresh Time count
+ * sys_time System Clock rate
+ *
+ * The counters are 16 bit counters. The maximum refresh time is
+ * 3.9us/clock cycle. The minimum is 400ns/clock cycle.
+ * Clock cycle is the FCRAM clock cycle?????
+ * If the cycle is FCRAM clock cycle, then sys_time parameter
+ * is not needed as there wont be configuration variation due to
+ * system clock cycle.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_fcram_refresh_time(npi_handle_t handle, uint32_t min_time,
+ uint32_t max_time, uint32_t sys_time)
+
+{
+
+ uint64_t offset;
+ fcram_ref_tmr_t refresh_timer_reg;
+ uint16_t max, min;
+
+ offset = FFLP_FCRAM_REF_TMR_REG;
+/* need to figure out how to dervive the numbers */
+ max = max_time * sys_time;
+ min = min_time * sys_time;
+/* for now, just set with #def values */
+
+ max = FCRAM_REFRESH_DEFAULT_MAX_TIME;
+ min = FCRAM_REFRESH_DEFAULT_MIN_TIME;
+ REG_PIO_READ64(handle, offset, &refresh_timer_reg.value);
+ refresh_timer_reg.bits.ldw.min = min;
+ refresh_timer_reg.bits.ldw.max = max;
+ REG_PIO_WRITE64(handle, offset, refresh_timer_reg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_hash_lookup_err_report
+ * Reports hash table (fcram) lookup errors
+ *
+ * Input
+ * err_stat Pointer to return Error bits
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_get_lookup_err_log(npi_handle_t handle,
+ hash_lookup_err_log_t *err_stat)
+
+{
+
+ hash_lookup_err_log1_t err_log1;
+ hash_lookup_err_log2_t err_log2;
+ uint64_t err_log1_offset, err_log2_offset;
+ err_log1.value = 0;
+ err_log2.value = 0;
+
+ err_log1_offset = HASH_LKUP_ERR_LOG1_REG;
+ err_log2_offset = HASH_LKUP_ERR_LOG2_REG;
+
+ REG_PIO_READ64(handle, err_log1_offset, &err_log1.value);
+ REG_PIO_READ64(handle, err_log2_offset, &err_log2.value);
+
+ if (err_log1.value) {
+/* nonzero means there are some errors */
+ err_stat->lookup_err = BIT_ENABLE;
+ err_stat->syndrome = err_log2.bits.ldw.syndrome;
+ err_stat->subarea = err_log2.bits.ldw.subarea;
+ err_stat->h1 = err_log2.bits.ldw.h1;
+ err_stat->multi_bit = err_log1.bits.ldw.mult_bit;
+ err_stat->multi_lkup = err_log1.bits.ldw.mult_lk;
+ err_stat->ecc_err = err_log1.bits.ldw.ecc_err;
+ err_stat->uncor_err = err_log1.bits.ldw.cu;
+ } else {
+ err_stat->lookup_err = BIT_DISABLE;
+ }
+
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_fflp_fcram_get_pio_err_log
+ * Reports hash table PIO read errors for the given partition.
+ * by default, it clears the error bit which was set by the HW.
+ *
+ * Input
+ * partid: partition ID
+ * err_stat Pointer to return Error bits
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_get_pio_err_log(npi_handle_t handle, part_id_t partid,
+ hash_pio_err_log_t *err_stat)
+{
+
+ hash_tbl_data_log_t err_log;
+ uint64_t offset;
+
+ if (!FCRAM_PARTITION_VALID(partid)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_get_pio_err_log:"
+ " Invalid Partition %d \n",
+ partid));
+ return (NPI_FFLP_FCRAM_PART_INVALID);
+ }
+
+ offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
+ FFLP_HASH_TBL_DATA_LOG_REG);
+
+ REG_PIO_READ64(handle, offset, &err_log.value);
+
+ if (err_log.bits.ldw.pio_err == BIT_ENABLE) {
+/* nonzero means there are some errors */
+ err_stat->pio_err = BIT_ENABLE;
+ err_stat->syndrome = err_log.bits.ldw.syndrome;
+ err_stat->addr = err_log.bits.ldw.fcram_addr;
+ err_log.value = 0;
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+ } else {
+ err_stat->pio_err = BIT_DISABLE;
+ }
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+/*
+ * npi_fflp_fcram_clr_pio_err_log
+ * Clears FCRAM PIO error status for the partition.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * partid: partition ID
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_clr_pio_err_log(npi_handle_t handle, part_id_t partid)
+{
+ uint64_t offset;
+
+ hash_tbl_data_log_t err_log;
+
+ if (!FCRAM_PARTITION_VALID(partid)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fcram_clr_pio_err_log:"
+ " Invalid Partition %d \n",
+ partid));
+
+ return (NPI_FFLP_FCRAM_PART_INVALID);
+ }
+
+ offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
+ FFLP_HASH_TBL_DATA_LOG_REG);
+
+ err_log.value = 0;
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+/*
+ * npi_fflp_tcam_get_err_log
+ * Reports TCAM PIO read and lookup errors.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various TCAM errors.
+ * will be updated if there are TCAM errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t
+npi_fflp_tcam_get_err_log(npi_handle_t handle, tcam_err_log_t *err_stat)
+{
+ tcam_err_t err_log;
+ uint64_t offset;
+
+ offset = FFLP_TCAM_ERR_REG;
+ err_log.value = 0;
+
+ REG_PIO_READ64(handle, offset, &err_log.value);
+
+ if (err_log.bits.ldw.err == BIT_ENABLE) {
+/* non-zero means err */
+ err_stat->tcam_err = BIT_ENABLE;
+ if (err_log.bits.ldw.p_ecc) {
+ err_stat->parity_err = 0;
+ err_stat->ecc_err = 1;
+ } else {
+ err_stat->parity_err = 1;
+ err_stat->ecc_err = 0;
+
+ }
+ err_stat->syndrome = err_log.bits.ldw.syndrome;
+ err_stat->location = err_log.bits.ldw.addr;
+
+
+ err_stat->multi_lkup = err_log.bits.ldw.mult;
+ /* now clear the error */
+ err_log.value = 0;
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+
+ } else {
+ err_stat->tcam_err = 0;
+ }
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_tcam_clr_err_log
+ * Clears TCAM PIO read and lookup error status.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various TCAM errors.
+ * will be updated if there are TCAM errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_tcam_clr_err_log(npi_handle_t handle)
+{
+ tcam_err_t err_log;
+ uint64_t offset;
+
+ offset = FFLP_TCAM_ERR_REG;
+ err_log.value = 0;
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_fcram_err_synd_test
+ * Tests the FCRAM error detection logic.
+ * The error detection logic for the syndrome is tested.
+ * tst0->synd (8bits) are set to select the syndrome bits
+ * to be XOR'ed
+ *
+ * Input
+ * syndrome_bits: Syndrome bits to select bits to be xor'ed
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t
+npi_fflp_fcram_err_synd_test(npi_handle_t handle, uint8_t syndrome_bits)
+{
+
+ uint64_t t0_offset;
+ fcram_err_tst0_t tst0;
+ t0_offset = FFLP_FCRAM_ERR_TST0_REG;
+
+ tst0.value = 0;
+ tst0.bits.ldw.syndrome_mask = syndrome_bits;
+
+ REG_PIO_WRITE64(handle, t0_offset, tst0.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_fflp_fcram_err_data_test
+ * Tests the FCRAM error detection logic.
+ * The error detection logic for the datapath is tested.
+ * bits [63:0] are set to select the data bits to be xor'ed
+ *
+ * Input
+ * data: data bits to select bits to be xor'ed
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t
+npi_fflp_fcram_err_data_test(npi_handle_t handle, fcram_err_data_t *data)
+{
+
+ uint64_t t1_offset, t2_offset;
+ fcram_err_tst1_t tst1; /* for data bits [31:0] */
+ fcram_err_tst2_t tst2; /* for data bits [63:32] */
+
+ t1_offset = FFLP_FCRAM_ERR_TST1_REG;
+ t2_offset = FFLP_FCRAM_ERR_TST2_REG;
+ tst1.value = 0;
+ tst2.value = 0;
+ tst1.bits.ldw.dat = data->bits.ldw.dat;
+ tst2.bits.ldw.dat = data->bits.hdw.dat;
+
+ REG_PIO_WRITE64(handle, t1_offset, tst1.value);
+ REG_PIO_WRITE64(handle, t2_offset, tst2.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+/*
+ * npi_fflp_cfg_enet_vlan_table_assoc
+ * associates port vlan id to rdc table.
+ *
+ * Input
+ * mac_portn port number
+ * vlan_id VLAN ID
+ * rdc_table RDC Table #
+ *
+ * Output
+ *
+ * NPI_SUCCESS Success
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_cfg_enet_vlan_table_assoc(npi_handle_t handle, uint8_t mac_portn,
+ vlan_id_t vlan_id, uint8_t rdc_table,
+ uint8_t priority)
+{
+
+ fflp_enet_vlan_tbl_t cfg;
+ uint64_t offset;
+ uint8_t vlan_parity[8] = {0, 1, 1, 2, 1, 2, 2, 3};
+ uint8_t parity_bit;
+ if (!FFLP_VLAN_VALID(vlan_id)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fflp_cfg_enet_vlan_table:"
+ " Invalid vlan ID %d \n",
+ vlan_id));
+ return (NPI_FFLP_VLAN_INVALID);
+ }
+
+ if (!FFLP_PORT_VALID(mac_portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fflp_cfg_enet_vlan_table:"
+ " Invalid port num %d \n",
+ mac_portn));
+ return (NPI_FFLP_PORT_INVALID);
+ }
+
+
+ if (!FFLP_RDC_TABLE_VALID(rdc_table)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " fflp_cfg_enet_vlan_table:"
+ " Invalid RDC Table %d \n",
+ rdc_table));
+ return (NPI_FFLP_RDC_TABLE_INVALID);
+ }
+
+ offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
+ REG_PIO_READ64(handle, offset, &cfg.value);
+
+ switch (mac_portn) {
+ case 0:
+ cfg.bits.ldw.vlanrdctbln0 = rdc_table;
+ if (priority)
+ cfg.bits.ldw.vpr0 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr0 = BIT_DISABLE;
+ /* set the parity bits */
+ parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
+ vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
+ cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
+ cfg.bits.ldw.parity0 = parity_bit & 0x1;
+ break;
+ case 1:
+ cfg.bits.ldw.vlanrdctbln1 = rdc_table;
+ if (priority)
+ cfg.bits.ldw.vpr1 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr1 = BIT_DISABLE;
+ /* set the parity bits */
+ parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
+ vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
+ cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
+ cfg.bits.ldw.parity0 = parity_bit & 0x1;
+
+ break;
+ case 2:
+ cfg.bits.ldw.vlanrdctbln2 = rdc_table;
+ if (priority)
+ cfg.bits.ldw.vpr2 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr2 = BIT_DISABLE;
+ /* set the parity bits */
+ parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
+ vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
+ cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
+ cfg.bits.ldw.parity1 = parity_bit & 0x1;
+
+ break;
+ case 3:
+ cfg.bits.ldw.vlanrdctbln3 = rdc_table;
+ if (priority)
+ cfg.bits.ldw.vpr3 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr3 = BIT_DISABLE;
+ /* set the parity bits */
+ parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
+ vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
+ cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
+ cfg.bits.ldw.parity1 = parity_bit & 0x1;
+ break;
+ default:
+ return (NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+ REG_PIO_WRITE64(handle, offset, cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_enet_vlan_table_set_pri
+ * sets the vlan based classification priority in respect to L2DA
+ * classification.
+ *
+ * Input
+ * mac_portn port number
+ * vlan_id VLAN ID
+ * priority priority
+ * 1: vlan classification has higher priority
+ * 0: l2da classification has higher priority
+ *
+ * Output
+ *
+ * NPI_SUCCESS Successful
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_enet_vlan_table_set_pri(npi_handle_t handle, uint8_t mac_portn,
+ vlan_id_t vlan_id, uint8_t priority)
+{
+
+ fflp_enet_vlan_tbl_t cfg;
+ uint64_t offset;
+ uint64_t old_value;
+
+ if (!FFLP_VLAN_VALID(vlan_id)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " enet_vlan_table set pri:"
+ " Invalid vlan ID %d \n",
+ vlan_id));
+ return (NPI_FFLP_VLAN_INVALID);
+ }
+
+ if (!FFLP_PORT_VALID(mac_portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " enet_vlan_table set pri:"
+ " Invalid port num %d \n",
+ mac_portn));
+ return (NPI_FFLP_PORT_INVALID);
+ }
+
+
+ offset = FFLP_ENET_VLAN_TBL_REG + (vlan_id << 3);
+ REG_PIO_READ64(handle, offset, &cfg.value);
+ old_value = cfg.value;
+ switch (mac_portn) {
+ case 0:
+ if (priority)
+ cfg.bits.ldw.vpr0 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr0 = BIT_DISABLE;
+ break;
+ case 1:
+ if (priority)
+ cfg.bits.ldw.vpr1 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr1 = BIT_DISABLE;
+ break;
+ case 2:
+ if (priority)
+ cfg.bits.ldw.vpr2 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr2 = BIT_DISABLE;
+ break;
+ case 3:
+ if (priority)
+ cfg.bits.ldw.vpr3 = BIT_ENABLE;
+ else
+ cfg.bits.ldw.vpr3 = BIT_DISABLE;
+ break;
+ default:
+ return (NPI_FFLP_SW_PARAM_ERROR);
+ }
+ if (old_value != cfg.value) {
+ if (mac_portn > 1)
+ cfg.bits.ldw.parity1++;
+ else
+ cfg.bits.ldw.parity0++;
+
+ REG_PIO_WRITE64(handle, offset, cfg.value);
+ }
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_vlan_table_clear
+ * Clears the vlan RDC table
+ *
+ * Input
+ * vlan_id VLAN ID
+ *
+ * Output
+ *
+ * NPI_SUCCESS Successful
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_vlan_table_clear(npi_handle_t handle, vlan_id_t vlan_id)
+{
+
+ uint64_t offset;
+ uint64_t clear = 0ULL;
+ vlan_id_t start_vlan = 0;
+
+ if ((vlan_id < start_vlan) || (vlan_id >= NXGE_MAX_VLANS)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " enet_vlan_table clear:"
+ " Invalid vlan ID %d \n",
+ vlan_id));
+ return (NPI_FFLP_VLAN_INVALID);
+ }
+
+
+ offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
+
+ REG_PIO_WRITE64(handle, offset, clear);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_vlan_tbl_get_err_log
+ * Reports VLAN Table errors.
+ * If there are VLAN Table errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various VLAN table errors.
+ * will be updated if there are errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t
+npi_fflp_vlan_tbl_get_err_log(npi_handle_t handle, vlan_tbl_err_log_t *err_stat)
+{
+ vlan_par_err_t err_log;
+ uint64_t offset;
+
+
+ offset = FFLP_VLAN_PAR_ERR_REG;
+ err_log.value = 0;
+
+ REG_PIO_READ64(handle, offset, &err_log.value);
+
+ if (err_log.bits.ldw.err == BIT_ENABLE) {
+/* non-zero means err */
+ err_stat->err = BIT_ENABLE;
+ err_stat->multi = err_log.bits.ldw.m_err;
+ err_stat->addr = err_log.bits.ldw.addr;
+ err_stat->data = err_log.bits.ldw.data;
+/* now clear the error */
+ err_log.value = 0;
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+
+ } else {
+ err_stat->err = 0;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fflp_vlan_tbl_clr_err_log
+ * Clears VLAN Table PIO error status.
+ * If there are VLAN Table errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various VLAN Table errors.
+ * will be updated if there are errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_vlan_tbl_clr_err_log(npi_handle_t handle)
+{
+ vlan_par_err_t err_log;
+ uint64_t offset;
+
+ offset = FFLP_VLAN_PAR_ERR_REG;
+ err_log.value = 0;
+
+ REG_PIO_WRITE64(handle, offset, err_log.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_set()
+ * Configures a user configurable ethernet class
+ *
+ * Input
+ * class: Ethernet Class class
+ * (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ * enet_type: 16 bit Ethernet Type value, corresponding ethernet bytes
+ * [13:14] in the frame.
+ *
+ * by default, the class will be disabled until explicitly enabled.
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_enet_usr_cls_set(npi_handle_t handle,
+ tcam_class_t class, uint16_t enet_type)
+{
+ uint64_t offset;
+ tcam_class_prg_ether_t cls_cfg;
+ cls_cfg.value = 0x0;
+
+/* check if etype is valid */
+
+ if (!TCAM_L2_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_enet_usr_cls_set:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+ offset = GET_TCAM_CLASS_OFFSET(class);
+
+/*
+ * etype check code
+ *
+ * if (check_fail)
+ * return (NPI_FAILURE | NPI_SW_ERROR);
+ */
+
+ cls_cfg.bits.ldw.etype = enet_type;
+ cls_cfg.bits.ldw.valid = BIT_DISABLE;
+ REG_PIO_WRITE64(handle, offset, cls_cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_enable()
+ * Enable previously configured TCAM user configurable Ethernet classes.
+ *
+ * Input
+ * class: Ethernet Class class
+ * (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_enet_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
+{
+ uint64_t offset;
+ tcam_class_prg_ether_t cls_cfg;
+
+ if (!TCAM_L2_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_enet_usr_cls_enable:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_TCAM_CLASS_OFFSET(class);
+
+ REG_PIO_READ64(handle, offset, &cls_cfg.value);
+ cls_cfg.bits.ldw.valid = BIT_ENABLE;
+ REG_PIO_WRITE64(handle, offset, cls_cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_disable()
+ * Disables previously configured TCAM user configurable Ethernet classes.
+ *
+ * Input
+ * class: Ethernet Class class
+ * (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_cfg_enet_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
+{
+ uint64_t offset;
+ tcam_class_prg_ether_t cls_cfg;
+
+ if (!TCAM_L2_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_enet_usr_cls_disable:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_TCAM_CLASS_OFFSET(class);
+
+ REG_PIO_READ64(handle, offset, &cls_cfg.value);
+ cls_cfg.bits.ldw.valid = BIT_DISABLE;
+
+ REG_PIO_WRITE64(handle, offset, cls_cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_set()
+ * Configures the TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ * tos: IP TOS bits
+ * tos_mask: IP TOS bits mask. bits with mask bits set will be used
+ * proto: IP Proto
+ * ver: IP Version
+ * by default, will the class is disabled until explicitly enabled
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_cfg_ip_usr_cls_set(npi_handle_t handle, tcam_class_t class,
+ uint8_t tos, uint8_t tos_mask,
+ uint8_t proto, uint8_t ver)
+{
+ uint64_t offset;
+ tcam_class_prg_ip_t ip_cls_cfg;
+
+ if (!TCAM_L3_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_usr_cls_set:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_TCAM_CLASS_OFFSET(class);
+
+ ip_cls_cfg.bits.ldw.pid = proto;
+ ip_cls_cfg.bits.ldw.ipver = ver;
+ ip_cls_cfg.bits.ldw.tos = tos;
+ ip_cls_cfg.bits.ldw.tosmask = tos_mask;
+ ip_cls_cfg.bits.ldw.valid = 0;
+ REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_enable()
+ * Enable previously configured TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_ip_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
+{
+ uint64_t offset;
+ tcam_class_prg_ip_t ip_cls_cfg;
+
+ if (!TCAM_L3_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_usr_cls_enable:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_TCAM_CLASS_OFFSET(class);
+ REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
+ ip_cls_cfg.bits.ldw.valid = 1;
+
+ REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_disable()
+ * Disables previously configured TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_cfg_ip_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
+{
+ uint64_t offset;
+ tcam_class_prg_ip_t ip_cls_cfg;
+
+ if (!TCAM_L3_USR_CLASS_VALID(class)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_usr_cls_disable:"
+ " Invalid class %d \n",
+ class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_TCAM_CLASS_OFFSET(class);
+
+ REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
+ ip_cls_cfg.bits.ldw.valid = 0;
+
+ REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_fflp_cfg_ip_cls_tcam_key ()
+ *
+ * Configures the TCAM key generation for the IP classes
+ *
+ * Input
+ * l3_class: IP class to configure key generation
+ * cfg: Configuration bits:
+ * discard: Discard all frames of this class
+ * use_ip_saddr: use ip src address (for ipv6)
+ * use_ip_daddr: use ip dest address (for ipv6)
+ * lookup_enable: Enable Lookup
+ *
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+npi_status_t
+npi_fflp_cfg_ip_cls_tcam_key(npi_handle_t handle,
+ tcam_class_t l3_class, tcam_key_cfg_t *cfg)
+{
+ uint64_t offset;
+ tcam_class_key_ip_t tcam_cls_cfg;
+
+ if (!(TCAM_L3_CLASS_VALID(l3_class))) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_cls_tcam_key:"
+ " Invalid class %d \n",
+ l3_class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ if ((cfg->use_ip_daddr) &&
+ (cfg->use_ip_saddr == cfg->use_ip_daddr)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_cls_tcam_key:"
+ " Invalid configuration %x for class %d \n",
+ *cfg, l3_class));
+ return (NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+
+ offset = GET_TCAM_KEY_OFFSET(l3_class);
+ tcam_cls_cfg.value = 0;
+
+ if (cfg->discard) {
+ tcam_cls_cfg.bits.ldw.discard = 1;
+ }
+
+ if (cfg->use_ip_saddr) {
+ tcam_cls_cfg.bits.ldw.ipaddr = 1;
+ }
+
+ if (cfg->use_ip_daddr) {
+ tcam_cls_cfg.bits.ldw.ipaddr = 0;
+ }
+
+ if (cfg->lookup_enable) {
+ tcam_cls_cfg.bits.ldw.tsel = 1;
+ }
+
+ REG_PIO_WRITE64(handle, offset, tcam_cls_cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_ip_cls_flow_key ()
+ *
+ * Configures the flow key generation for the IP classes
+ * Flow key is used to generate the H1 hash function value
+ * The fields used for the generation are configured using this
+ * NPI function.
+ *
+ * Input
+ * l3_class: IP class to configure flow key generation
+ * cfg: Configuration bits:
+ * use_proto: Use IP proto field
+ * use_dport: use l4 destination port
+ * use_sport: use l4 source port
+ * ip_opts_exist: IP Options Present
+ * use_daddr: use ip dest address
+ * use_saddr: use ip source address
+ * use_vlan: use VLAN ID
+ * use_l2da: use L2 Dest MAC Address
+ * use_portnum: use L2 virtual port number
+ *
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_HW_ERROR
+ * NPI_SW_ERROR
+ *
+ */
+
+
+
+npi_status_t
+npi_fflp_cfg_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
+ flow_key_cfg_t *cfg)
+{
+ uint64_t offset;
+ flow_class_key_ip_t flow_cfg_reg;
+
+
+ if (!(TCAM_L3_CLASS_VALID(l3_class))) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_cls_flow_key:"
+ " Invalid class %d \n",
+ l3_class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+
+ offset = GET_FLOW_KEY_OFFSET(l3_class);
+ flow_cfg_reg.value = 0; /* default */
+
+ if (cfg->use_proto) {
+ flow_cfg_reg.bits.ldw.proto = 1;
+ }
+
+ if (cfg->use_dport) {
+ flow_cfg_reg.bits.ldw.l4_1 = 2;
+ if (cfg->ip_opts_exist)
+ flow_cfg_reg.bits.ldw.l4_1 = 3;
+ }
+
+ if (cfg->use_sport) {
+ flow_cfg_reg.bits.ldw.l4_0 = 2;
+ if (cfg->ip_opts_exist)
+ flow_cfg_reg.bits.ldw.l4_0 = 3;
+ }
+
+ if (cfg->use_daddr) {
+ flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
+ }
+
+ if (cfg->use_saddr) {
+ flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
+ }
+
+ if (cfg->use_vlan) {
+ flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
+ }
+
+ if (cfg->use_l2da) {
+ flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
+ }
+
+ if (cfg->use_portnum) {
+ flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
+ }
+
+ REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+npi_status_t
+npi_fflp_cfg_ip_cls_flow_key_get(npi_handle_t handle,
+ tcam_class_t l3_class,
+ flow_key_cfg_t *cfg)
+{
+ uint64_t offset;
+ flow_class_key_ip_t flow_cfg_reg;
+
+
+ if (!(TCAM_L3_CLASS_VALID(l3_class))) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_cls_flow_key:"
+ " Invalid class %d \n",
+ l3_class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+ offset = GET_FLOW_KEY_OFFSET(l3_class);
+
+ cfg->use_proto = 0;
+ cfg->use_dport = 0;
+ cfg->use_sport = 0;
+ cfg->ip_opts_exist = 0;
+ cfg->use_daddr = 0;
+ cfg->use_saddr = 0;
+ cfg->use_vlan = 0;
+ cfg->use_l2da = 0;
+ cfg->use_portnum = 0;
+
+ REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
+
+ if (flow_cfg_reg.bits.ldw.proto) {
+ cfg->use_proto = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
+ cfg->use_dport = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
+ cfg->use_dport = 1;
+ cfg->ip_opts_exist = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
+ cfg->use_sport = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
+ cfg->use_sport = 1;
+ cfg->ip_opts_exist = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.ipda) {
+ cfg->use_daddr = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.ipsa) {
+ cfg->use_saddr = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.vlan) {
+ cfg->use_vlan = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.l2da) {
+ cfg->use_l2da = 1;
+ }
+
+ if (flow_cfg_reg.bits.ldw.port) {
+ cfg->use_portnum = 1;
+ }
+
+ NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
+ " npi_fflp_cfg_ip_cls_flow_get %llx \n",
+ flow_cfg_reg.value));
+
+ return (NPI_SUCCESS);
+
+}
+
+
+npi_status_t
+npi_fflp_cfg_ip_cls_tcam_key_get(npi_handle_t handle,
+ tcam_class_t l3_class, tcam_key_cfg_t *cfg)
+{
+ uint64_t offset;
+ tcam_class_key_ip_t tcam_cls_cfg;
+
+ if (!(TCAM_L3_CLASS_VALID(l3_class))) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_ip_cls_tcam_key_get:"
+ " Invalid class %d \n",
+ l3_class));
+ return (NPI_FFLP_TCAM_CLASS_INVALID);
+ }
+
+
+ offset = GET_TCAM_KEY_OFFSET(l3_class);
+
+ REG_PIO_READ64(handle, offset, &tcam_cls_cfg.value);
+
+ cfg->discard = 0;
+ cfg->use_ip_saddr = 0;
+ cfg->use_ip_daddr = 1;
+ cfg->lookup_enable = 0;
+
+ if (tcam_cls_cfg.bits.ldw.discard)
+ cfg->discard = 1;
+
+ if (tcam_cls_cfg.bits.ldw.ipaddr) {
+ cfg->use_ip_saddr = 1;
+ cfg->use_ip_daddr = 0;
+ }
+
+ if (tcam_cls_cfg.bits.ldw.tsel) {
+ cfg->lookup_enable = 1;
+ }
+
+ NPI_DEBUG_MSG((handle.function, NPI_CTL,
+ " npi_fflp_cfg_ip_cls_tcam_key_get %llx \n",
+ tcam_cls_cfg.value));
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fflp_cfg_fcram_access ()
+ *
+ * Sets the ratio between the FCRAM pio and lookup access
+ * Input:
+ * access_ratio: 0 Lookup has the highest priority
+ * 15 PIO has maximum possible priority
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_fcram_access(npi_handle_t handle, uint8_t access_ratio)
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+ if (access_ratio > 0xf) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_fcram_access:"
+ " Invalid access ratio %d \n",
+ access_ratio));
+ return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 0;
+ fflp_cfg.bits.ldw.fcramratio = access_ratio;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_fflp_cfg_tcam_access ()
+ *
+ * Sets the ratio between the TCAM pio and lookup access
+ * Input:
+ * access_ratio: 0 Lookup has the highest priority
+ * 15 PIO has maximum possible priority
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_tcam_access(npi_handle_t handle, uint8_t access_ratio)
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+ if (access_ratio > 0xf) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_cfg_tcram_access:"
+ " Invalid access ratio %d \n",
+ access_ratio));
+ return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 0;
+ fflp_cfg.bits.ldw.camratio = access_ratio;
+/* since the cam latency is fixed, we might set it here */
+ fflp_cfg.bits.ldw.camlatency = TCAM_DEFAULT_LATENCY;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+
+/*
+ * npi_fflp_cfg_hash_h1poly()
+ * Initializes the H1 hash generation logic.
+ *
+ * Input
+ * init_value: The initial value (seed)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_hash_h1poly(npi_handle_t handle, uint32_t init_value)
+{
+
+
+ hash_h1poly_t h1_cfg;
+ uint64_t offset;
+ offset = FFLP_H1POLY_REG;
+
+ h1_cfg.value = 0;
+ h1_cfg.bits.ldw.init_value = init_value;
+
+ REG_PIO_WRITE64(handle, offset, h1_cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_fflp_cfg_hash_h2poly()
+ * Initializes the H2 hash generation logic.
+ *
+ * Input
+ * init_value: The initial value (seed)
+ *
+ * Return
+ * NPI_SUCCESS
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_hash_h2poly(npi_handle_t handle, uint16_t init_value)
+{
+
+
+ hash_h2poly_t h2_cfg;
+ uint64_t offset;
+ offset = FFLP_H2POLY_REG;
+
+ h2_cfg.value = 0;
+ h2_cfg.bits.ldw.init_value = init_value;
+
+ REG_PIO_WRITE64(handle, offset, h2_cfg.value);
+ return (NPI_SUCCESS);
+
+
+}
+
+
+
+/*
+ * npi_fflp_cfg_reset
+ * Initializes the FCRAM reset sequence.
+ *
+ * Input
+ * strength: FCRAM Drive strength
+ * strong, weak or normal
+ * HW recommended value:
+ * qs: FCRAM QS mode selection
+ * qs mode or free running
+ * HW recommended value is:
+ * type: reset type:
+ * FFLP_ONLY
+ * FFLP_FCRAM
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_fcram_reset(npi_handle_t handle,
+ fflp_fcram_output_drive_t strength,
+ fflp_fcram_qs_t qs)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+
+ /* These bits have to be configured before FCRAM reset is issued */
+ fflp_cfg.value = 0;
+ fflp_cfg.bits.ldw.pio_fio_rst = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ NXGE_DELAY(5); /* TODO: What is the correct delay? */
+
+ fflp_cfg.bits.ldw.pio_fio_rst = 0;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ fflp_cfg.bits.ldw.fcramqs = qs;
+ fflp_cfg.bits.ldw.fcramoutdr = strength;
+ fflp_cfg.bits.ldw.fflpinitdone = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+npi_status_t
+npi_fflp_cfg_init_done(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+npi_status_t
+npi_fflp_cfg_init_start(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.fflpinitdone = 0;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * Enables the TCAM search function.
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_tcam_enable(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.tcam_disable = 0;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+/*
+ * Disables the TCAM search function.
+ * While the TCAM is in disabled state, all TCAM matches would return NO_MATCH
+ *
+ */
+
+npi_status_t
+npi_fflp_cfg_tcam_disable(npi_handle_t handle)
+
+{
+
+ fflp_cfg_1_t fflp_cfg;
+ uint64_t offset;
+ offset = FFLP_CFG_1_REG;
+ REG_PIO_READ64(handle, offset, &fflp_cfg.value);
+ fflp_cfg.bits.ldw.tcam_disable = 1;
+ REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+/*
+ * npi_rxdma_event_mask_config():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cfgp - pointer to NPI defined event mask
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR
+ *
+ */
+npi_status_t
+npi_fflp_event_mask_config(npi_handle_t handle, io_op_t op_mode,
+ fflp_event_mask_cfg_t *mask_cfgp)
+{
+ int status = NPI_SUCCESS;
+ fflp_err_mask_t mask_reg;
+
+ switch (op_mode) {
+ case OP_GET:
+
+ REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
+ *mask_cfgp = mask_reg.value & FFLP_ERR_MASK_ALL;
+ break;
+
+ case OP_SET:
+ mask_reg.value = (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
+ REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
+ break;
+
+ case OP_UPDATE:
+ REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
+ mask_reg.value |= (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
+ REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
+ break;
+
+ case OP_CLEAR:
+ mask_reg.value = FFLP_ERR_MASK_ALL;
+ REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fflp_event_mask_config",
+ " eventmask <0x%x>", op_mode));
+ return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
+ }
+
+ return (status);
+}
+
+/* Read vlan error bits */
+
+void
+npi_fflp_vlan_error_get(npi_handle_t handle, p_vlan_par_err_t p_err)
+{
+ REG_PIO_READ64(handle, FFLP_VLAN_PAR_ERR_REG, &p_err->value);
+}
+
+/* clear vlan error bits */
+void
+npi_fflp_vlan_error_clear(npi_handle_t handle)
+{
+ vlan_par_err_t p_err;
+ p_err.value = 0;
+ p_err.bits.ldw.m_err = 0;
+ p_err.bits.ldw.err = 0;
+ REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, p_err.value);
+
+}
+
+
+/* Read TCAM error bits */
+
+void
+npi_fflp_tcam_error_get(npi_handle_t handle, p_tcam_err_t p_err)
+{
+ REG_PIO_READ64(handle, FFLP_TCAM_ERR_REG, &p_err->value);
+}
+
+/* clear TCAM error bits */
+void
+npi_fflp_tcam_error_clear(npi_handle_t handle)
+{
+ tcam_err_t p_err;
+ p_err.value = 0;
+ p_err.bits.ldw.p_ecc = 0;
+ p_err.bits.ldw.mult = 0;
+ p_err.bits.ldw.err = 0;
+ REG_PIO_WRITE64(handle, FFLP_TCAM_ERR_REG, p_err.value);
+
+}
+
+
+/* Read FCRAM error bits */
+
+void
+npi_fflp_fcram_error_get(npi_handle_t handle,
+ p_hash_tbl_data_log_t p_err, uint8_t partition)
+{
+ uint64_t offset;
+ offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
+ REG_PIO_READ64(handle, offset, &p_err->value);
+}
+
+/* clear FCRAM error bits */
+void
+npi_fflp_fcram_error_clear(npi_handle_t handle, uint8_t partition)
+{
+ hash_tbl_data_log_t p_err;
+ uint64_t offset;
+ p_err.value = 0;
+ p_err.bits.ldw.pio_err = 0;
+ offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
+
+ REG_PIO_WRITE64(handle, offset,
+ p_err.value);
+
+}
+
+
+/* Read FCRAM lookup error log1 bits */
+
+void
+npi_fflp_fcram_error_log1_get(npi_handle_t handle,
+ p_hash_lookup_err_log1_t log1)
+{
+ REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG1_REG,
+ &log1->value);
+}
+
+
+
+/* Read FCRAM lookup error log2 bits */
+
+void
+npi_fflp_fcram_error_log2_get(npi_handle_t handle,
+ p_hash_lookup_err_log2_t log2)
+{
+ REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG2_REG,
+ &log2->value);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.h b/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.h
new file mode 100644
index 0000000000..b2de964973
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_fflp.h
@@ -0,0 +1,1187 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_FFLP_H
+#define _NPI_FFLP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <npi.h>
+#include <nxge_fflp_hw.h>
+#include <nxge_fflp.h>
+
+
+typedef uint8_t part_id_t;
+typedef uint8_t tcam_location_t;
+typedef uint16_t vlan_id_t;
+
+typedef enum _tcam_op {
+ TCAM_RWC_STAT = 0x1,
+ TCAM_RWC_MATCH = 0x2
+} tcam_op_t;
+
+
+#define NPI_TCAM_COMP_NO_MATCH 0x8000000000000ULL
+
+/*
+ * NPI FFLP ERROR Codes
+ */
+
+#define NPI_FFLP_BLK_CODE FFLP_BLK_ID << 8
+#define NPI_FFLP_ERROR (NPI_FAILURE | NPI_FFLP_BLK_CODE)
+#define NPI_TCAM_ERROR 0x10
+#define NPI_FCRAM_ERROR 0x20
+#define NPI_GEN_FFLP 0x30
+#define NPI_FFLP_SW_PARAM_ERROR 0x40
+#define NPI_FFLP_HW_ERROR 0x80
+
+
+#define NPI_FFLP_RESET_ERROR (NPI_FFLP_ERROR | NPI_GEN_FFLP | RESET_FAILED)
+#define NPI_FFLP_RDC_TABLE_INVALID (NPI_FFLP_ERROR | RDC_TAB_INVALID)
+#define NPI_FFLP_VLAN_INVALID (NPI_FFLP_ERROR | VLAN_INVALID)
+#define NPI_FFLP_PORT_INVALID (NPI_FFLP_ERROR | PORT_INVALID)
+#define NPI_FFLP_TCAM_RD_ERROR \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | READ_FAILED)
+#define NPI_FFLP_TCAM_WR_ERROR \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | WRITE_FAILED)
+#define NPI_FFLP_TCAM_LOC_INVALID \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | LOCATION_INVALID)
+#define NPI_FFLP_ASC_RAM_RD_ERROR \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | READ_FAILED)
+#define NPI_FFLP_ASC_RAM_WR_ERROR \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | WRITE_FAILED)
+#define NPI_FFLP_FCRAM_READ_ERROR \
+ (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | READ_FAILED)
+#define NPI_FFLP_FCRAM_WR_ERROR \
+ (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | WRITE_FAILED)
+#define NPI_FFLP_FCRAM_PART_INVALID \
+ (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | RDC_TAB_INVALID)
+#define NPI_FFLP_FCRAM_LOC_INVALID \
+ (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | LOCATION_INVALID)
+
+#define TCAM_CLASS_INVALID \
+ (NPI_FFLP_SW_PARAM_ERROR | 0xb)
+/* have only 0xc, 0xd, 0xe and 0xf left for sw error codes */
+#define NPI_FFLP_TCAM_CLASS_INVALID \
+ (NPI_FFLP_ERROR | NPI_TCAM_ERROR | TCAM_CLASS_INVALID)
+#define NPI_FFLP_TCAM_HW_ERROR \
+ (NPI_FFLP_ERROR | NPI_FFLP_HW_ERROR | NPI_TCAM_ERROR)
+#define NPI_FFLP_FCRAM_HW_ERROR \
+ (NPI_FFLP_ERROR | NPI_FFLP_HW_ERROR | NPI_FCRAM_ERROR)
+
+
+/*
+ * FFLP NPI defined event masks (mapped to the hardware defined masks).
+ */
+typedef enum _fflp_event_mask_cfg_e {
+ CFG_FFLP_ENT_MSK_VLAN_MASK = FFLP_ERR_VLAN_MASK,
+ CFG_FFLP_ENT_MSK_TCAM_MASK = FFLP_ERR_TCAM_MASK,
+ CFG_FFLP_ENT_MSK_HASH_TBL_LKUP_MASK = FFLP_ERR_HASH_TBL_LKUP_MASK,
+ CFG_FFLP_ENT_MSK_HASH_TBL_DAT_MASK = FFLP_ERR_HASH_TBL_DAT_MASK,
+
+ CFG_FFLP_MASK_ALL = (FFLP_ERR_VLAN_MASK | FFLP_ERR_TCAM_MASK |
+ FFLP_ERR_HASH_TBL_LKUP_MASK |
+ FFLP_ERR_HASH_TBL_DAT_MASK)
+} fflp_event_mask_cfg_t;
+
+
+/* FFLP FCRAM Related Functions */
+/* The following are FCRAM datapath functions */
+
+/*
+ * npi_fflp_fcram_entry_write ()
+ * Populates an FCRAM entry
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: Index to the FCRAM.
+ * Corresponds to last 20 bits of H1 value
+ * fcram_ptr: Pointer to the FCRAM contents to be used for writing
+ * format: Entry Format. Determines the size of the write.
+ * FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit write)
+ * FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit write)
+ * FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit write)
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_fcram_entry_write(npi_handle_t, part_id_t,
+ uint32_t, fcram_entry_t *,
+ fcram_entry_format_t);
+
+/*
+ * npi_fflp_fcram_entry_read ()
+ * Reads an FCRAM entry
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: Index to the FCRAM.
+ * Corresponds to last 20 bits of H1 value
+ * fcram_ptr: Pointer to the FCRAM contents to be updated
+ * format: Entry Format. Determines the size of the read.
+ * FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit read)
+ * FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit read )
+ * FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit read )
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ */
+
+npi_status_t npi_fflp_fcram_entry_read(npi_handle_t, part_id_t,
+ uint32_t, fcram_entry_t *,
+ fcram_entry_format_t);
+
+/*
+ * npi_fflp_fcram_entry_invalidate ()
+ * Invalidate FCRAM entry at the given location
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the FCRAM/hash entry.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t
+npi_fflp_fcram_entry_invalidate(npi_handle_t, part_id_t,
+ uint32_t);
+
+/*
+ * npi_fflp_fcram_subarea_write ()
+ * Writes to FCRAM entry subarea i.e the 8 bytes within the 64 bytes pointed by
+ * last 20 bits of H1. Effectively, this accesses specific 8 bytes within the
+ * hash table bucket.
+ *
+ * |-----------------| <-- H1
+ * | subarea 0 |
+ * |_________________|
+ * | Subarea 1 |
+ * |_________________|
+ * | ....... |
+ * |_________________|
+ * | Subarea 7 |
+ * |_________________|
+ *
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the subarea. It is derived from:
+ * Bucket = [19:15][14:0] (20 bits of H1)
+ * location = (Bucket << 3 ) + subarea * 8
+ * = [22:18][17:3] || subarea * 8
+ * data: Data
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t npi_fflp_fcram_subarea_write(npi_handle_t, part_id_t,
+ uint32_t, uint64_t);
+/*
+ * npi_fflp_fcram_subarea_read ()
+ * Reads an FCRAM entry subarea i.e the 8 bytes within the 64 bytes pointed by
+ * last 20 bits of H1. Effectively, this accesses specific 8 bytes within the
+ * hash table bucket.
+ *
+ * H1--> |-----------------|
+ * | subarea 0 |
+ * |_________________|
+ * | Subarea 1 |
+ * |_________________|
+ * | ....... |
+ * |_________________|
+ * | Subarea 7 |
+ * |_________________|
+ *
+ * Inputs:
+ * handle: opaque handle interpreted by the underlying OS
+ * partid: Partition ID
+ * location: location of the subarea. It is derived from:
+ * Bucket = [19:15][14:0] (20 bits of H1)
+ * location = (Bucket << 3 ) + subarea * 8
+ * = [22:18][17:3] || subarea * 8
+ * data: ptr do write subarea contents to.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_fcram_subarea_read (npi_handle_t,
+ part_id_t, uint32_t, uint64_t *);
+
+
+/* The following are zero function fflp configuration functions */
+/*
+ * npi_fflp_fcram_config_partition()
+ * Partitions and configures the FCRAM
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ * part_size Size of the partition
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t npi_fflp_cfg_fcram_partition(npi_handle_t, part_id_t,
+ uint8_t, uint8_t);
+
+/*
+ * npi_fflp_fcram_partition_enable
+ * Enable previously configured FCRAM partition
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ *
+ * Return
+ * 0 Successful
+ * Non zero error code Enable failed, and reason.
+ *
+ */
+npi_status_t npi_fflp_cfg_fcram_partition_enable(npi_handle_t,
+ part_id_t);
+
+/*
+ * npi_fflp_fcram_partition_disable
+ * Disable previously configured FCRAM partition
+ *
+ * Input
+ * partid partition ID
+ * Corresponds to the RDC table
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_fcram_partition_disable(npi_handle_t,
+ part_id_t);
+
+
+/*
+ * npi_fflp_cfg_fcram_reset
+ * Initializes the FCRAM reset sequence (including FFLP).
+ *
+ * Input
+ * strength: FCRAM Drive strength
+ * strong, weak or normal
+ * HW recommended value:
+ * qs: FCRAM QS mode selection
+ * qs mode or free running
+ * HW recommended value is:
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_fcram_reset(npi_handle_t,
+ fflp_fcram_output_drive_t,
+ fflp_fcram_qs_t);
+
+
+
+/*
+ * npi_fflp_cfg_tcam_reset
+ * Initializes the FFLP reset sequence
+ * Doesn't configure the FCRAM params.
+ *
+ * Input
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_tcam_reset(npi_handle_t);
+
+/*
+ * npi_fflp_cfg_tcam_enable
+ * Enables the TCAM function
+ *
+ * Input
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_tcam_enable(npi_handle_t);
+
+/*
+ * npi_fflp_cfg_tcam_disable
+ * Enables the TCAM function
+ *
+ * Input
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_tcam_disable(npi_handle_t);
+
+
+/*
+ * npi_fflp_cfg_cam_errorcheck_disable
+ * Disables FCRAM and TCAM error checking
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_cam_errorcheck_disable(npi_handle_t);
+
+/*
+ * npi_fflp_cfg_cam_errorcheck_enable
+ * Enables FCRAM and TCAM error checking
+ *
+ * Input
+ *
+ *
+ * Return
+ * 0 Successful
+ * Non zero error code Enable failed, and reason.
+ *
+ */
+npi_status_t npi_fflp_cfg_cam_errorcheck_enable(npi_handle_t);
+
+
+/*
+ * npi_fflp_cfg_llcsnap_enable
+ * Enables input parser llcsnap recognition
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ */
+npi_status_t npi_fflp_cfg_llcsnap_enable(npi_handle_t);
+
+/*
+ * npi_fflp_cam_llcsnap_disable
+ * Disables input parser llcsnap recognition
+ *
+ * Input
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ */
+
+npi_status_t npi_fflp_cfg_llcsnap_disable(npi_handle_t);
+
+/*
+ * npi_fflp_config_fcram_refresh
+ * Set FCRAM min and max refresh time.
+ *
+ * Input
+ * min_time Minimum Refresh time count
+ * max_time maximum Refresh Time count
+ * sys_time System Clock rate
+ *
+ * The counters are 16 bit counters. The maximum refresh time is
+ * 3.9us/clock cycle. The minimum is 400ns/clock cycle.
+ * Clock cycle is the FCRAM clock cycle?????
+ * If the cycle is FCRAM clock cycle, then sys_time parameter
+ * is not needed as there wont be configuration variation due to
+ * system clock cycle.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_fcram_refresh_time(npi_handle_t,
+ uint32_t, uint32_t, uint32_t);
+
+
+/*
+ * npi_fflp_cfg_fcram_access ()
+ *
+ * Sets the ratio between the FCRAM pio and lookup access
+ * Input:
+ * access_ratio: 0 Lookup has the highest priority
+ * 15 PIO has maximum possible priority
+ *
+ */
+
+npi_status_t npi_fflp_cfg_fcram_access(npi_handle_t,
+ uint8_t);
+
+
+/*
+ * npi_fflp_cfg_tcam_access ()
+ *
+ * Sets the ratio between the TCAM pio and lookup access
+ * Input:
+ * access_ratio: 0 Lookup has the highest priority
+ * 15 PIO has maximum possible priority
+ *
+ */
+
+npi_status_t npi_fflp_cfg_tcam_access(npi_handle_t, uint8_t);
+
+
+/*
+ * npi_fflp_hash_lookup_err_report
+ * Reports hash table (fcram) lookup errors
+ *
+ * Input
+ * status Pointer to return Error bits
+ *
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_fcram_get_lookup_err_log(npi_handle_t,
+ hash_lookup_err_log_t *);
+
+
+
+/*
+ * npi_fflp_fcram_get_pio_err_log
+ * Reports hash table PIO read errors.
+ *
+ * Input
+ * partid: partition ID
+ * err_stat pointer to return Error bits
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+npi_status_t npi_fflp_fcram_get_pio_err_log(npi_handle_t,
+ part_id_t, hash_pio_err_log_t *);
+
+
+/*
+ * npi_fflp_fcram_clr_pio_err_log
+ * Clears FCRAM PIO error status for the partition.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * partid: partition ID
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t npi_fflp_fcram_clr_pio_err_log(npi_handle_t,
+ part_id_t);
+
+
+
+/*
+ * npi_fflp_fcram_err_data_test
+ * Tests the FCRAM error detection logic.
+ * The error detection logic for the datapath is tested.
+ * bits [63:0] are set to select the data bits to be xored
+ *
+ * Input
+ * data: data bits to select bits to be xored
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t npi_fflp_fcram_err_data_test(npi_handle_t, fcram_err_data_t *);
+
+
+/*
+ * npi_fflp_fcram_err_synd_test
+ * Tests the FCRAM error detection logic.
+ * The error detection logic for the syndrome is tested.
+ * tst0->synd (8bits) are set to select the syndrome bits
+ * to be XOR'ed
+ *
+ * Input
+ * syndrome_bits: Syndrome bits to select bits to be xor'ed
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t npi_fflp_fcram_err_synd_test(npi_handle_t, uint8_t);
+
+
+/*
+ * npi_fflp_cfg_vlan_table_clear
+ * Clears the vlan RDC table
+ *
+ * Input
+ * vlan_id VLAN ID
+ *
+ * Output
+ *
+ * NPI_SUCCESS Successful
+ *
+ */
+
+npi_status_t npi_fflp_cfg_vlan_table_clear(npi_handle_t, vlan_id_t);
+
+/*
+ * npi_fflp_cfg_enet_vlan_table_assoc
+ * associates port vlan id to rdc table and sets the priority
+ * in respect to L2DA rdc table.
+ *
+ * Input
+ * mac_portn port number
+ * vlan_id VLAN ID
+ * rdc_table RDC Table #
+ * priority priority
+ * 1: vlan classification has higher priority
+ * 0: l2da classification has higher priority
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_enet_vlan_table_assoc(npi_handle_t,
+ uint8_t, vlan_id_t,
+ uint8_t, uint8_t);
+
+
+/*
+ * npi_fflp_cfg_enet_vlan_table_set_pri
+ * sets the vlan based classification priority in respect to
+ * L2DA classification.
+ *
+ * Input
+ * mac_portn port number
+ * vlan_id VLAN ID
+ * priority priority
+ * 1: vlan classification has higher priority
+ * 0: l2da classification has higher priority
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_enet_vlan_table_set_pri(npi_handle_t,
+ uint8_t, vlan_id_t,
+ uint8_t);
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_set()
+ * Configures a user configurable ethernet class
+ *
+ * Input
+ * class: Ethernet Class
+ * class (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ * enet_type: 16 bit Ethernet Type value, corresponding ethernet bytes
+ * [13:14] in the frame.
+ *
+ * by default, the class will be disabled until explicitly enabled.
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ *
+ *
+ */
+
+npi_status_t npi_fflp_cfg_enet_usr_cls_set(npi_handle_t,
+ tcam_class_t, uint16_t);
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_enable()
+ * Enable previously configured TCAM user configurable Ethernet classes.
+ *
+ * Input
+ * class: Ethernet Class class
+ * (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_enet_usr_cls_enable(npi_handle_t, tcam_class_t);
+
+/*
+ * npi_fflp_cfg_enet_usr_cls_disable()
+ * Disables previously configured TCAM user configurable Ethernet classes.
+ *
+ * Input
+ * class: Ethernet Class
+ * class = (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t npi_fflp_cfg_enet_usr_cls_disable(npi_handle_t, tcam_class_t);
+
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_set()
+ * Configures the TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ * tos: IP TOS bits
+ * tos_mask: IP TOS bits mask. bits with mask bits set will be used
+ * proto: IP Proto
+ * ver: IP Version
+ * by default, will the class is disabled until explicitly enabled
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_ip_usr_cls_set(npi_handle_t,
+ tcam_class_t,
+ uint8_t, uint8_t,
+ uint8_t, uint8_t);
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_enable()
+ * Enable previously configured TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_ip_usr_cls_enable(npi_handle_t, tcam_class_t);
+
+/*
+ * npi_fflp_cfg_ip_usr_cls_disable()
+ * Disables previously configured TCAM user configurable IP classes.
+ *
+ * Input
+ * class: IP Class
+ * (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t npi_fflp_cfg_ip_usr_cls_disable(npi_handle_t, tcam_class_t);
+
+
+/*
+ * npi_fflp_cfg_ip_cls_tcam_key ()
+ *
+ * Configures the TCAM key generation for the IP classes
+ *
+ * Input
+ * l3_class: IP class to configure key generation
+ * cfg: Configuration bits:
+ * discard: Discard all frames of this class
+ * use_ip_saddr: use ip src address (for ipv6)
+ * use_ip_daddr: use ip dest address (for ipv6)
+ * lookup_enable: Enable Lookup
+ *
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t npi_fflp_cfg_ip_cls_tcam_key(npi_handle_t,
+ tcam_class_t, tcam_key_cfg_t *);
+
+/*
+ * npi_fflp_cfg_ip_cls_flow_key ()
+ *
+ * Configures the flow key generation for the IP classes
+ * Flow key is used to generate the H1 hash function value
+ * The fields used for the generation are configured using this
+ * NPI function.
+ *
+ * Input
+ * l3_class: IP class to configure flow key generation
+ * cfg: Configuration bits:
+ * use_proto: Use IP proto field
+ * use_dport: use l4 destination port
+ * use_sport: use l4 source port
+ * ip_opts_exist: IP Options Present
+ * use_daddr: use ip dest address
+ * use_saddr: use ip source address
+ * use_vlan: use VLAN ID
+ * use_l2da: use L2 Dest MAC Address
+ * use_portnum: use L2 virtual port number
+ *
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_ip_cls_flow_key(npi_handle_t,
+ tcam_class_t, flow_key_cfg_t *);
+
+
+
+npi_status_t npi_fflp_cfg_ip_cls_flow_key_get(npi_handle_t,
+ tcam_class_t,
+ flow_key_cfg_t *);
+
+
+npi_status_t npi_fflp_cfg_ip_cls_tcam_key_get(npi_handle_t,
+ tcam_class_t, tcam_key_cfg_t *);
+/*
+ * npi_fflp_cfg_hash_h1poly()
+ * Initializes the H1 hash generation logic.
+ *
+ * Input
+ * init_value: The initial value (seed)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_hash_h1poly(npi_handle_t, uint32_t);
+
+
+
+/*
+ * npi_fflp_cfg_hash_h2poly()
+ * Initializes the H2 hash generation logic.
+ *
+ * Input
+ * init_value: The initial value (seed)
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_cfg_hash_h2poly(npi_handle_t, uint16_t);
+
+
+/*
+ * Reset the fflp block (actually the FCRAM)
+ * Waits until reset is completed
+ *
+ * input
+ * strength fcram output drive strength: weak, normal or strong
+ * qs qs mode. Normal or free running
+ *
+ * return value
+ * NPI_SUCCESS
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ */
+
+npi_status_t npi_fflp_fcram_reset(npi_handle_t,
+ fflp_fcram_output_drive_t,
+ fflp_fcram_qs_t);
+
+
+/* FFLP TCAM Related Functions */
+
+
+/*
+ * npi_fflp_tcam_entry_match()
+ *
+ * Tests for TCAM match of the tcam entry
+ *
+ * Input
+ * tcam_ptr
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+int npi_fflp_tcam_entry_match(npi_handle_t, tcam_entry_t *);
+
+/*
+ * npi_fflp_tcam_entry_write()
+ *
+ * writes a tcam entry at the TCAM location, location
+ *
+ * Input
+ * location
+ * tcam_ptr
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_tcam_entry_write(npi_handle_t,
+ tcam_location_t,
+ tcam_entry_t *);
+
+/*
+ * npi_fflp_tcam_entry_read ()
+ *
+ * Reads a tcam entry from the TCAM location, location
+ *
+ * Input:
+ * location
+ * tcam_ptr
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+
+npi_status_t npi_fflp_tcam_entry_read(npi_handle_t,
+ tcam_location_t,
+ tcam_entry_t *);
+
+/*
+ * npi_fflp_tcam_entry_invalidate()
+ *
+ * invalidates entry at tcam location
+ *
+ * Input
+ * location
+ *
+ * Return
+ * NPI_SUCCESS
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_tcam_entry_invalidate(npi_handle_t,
+ tcam_location_t);
+
+
+/*
+ * npi_fflp_tcam_asc_ram_entry_write()
+ *
+ * writes a tcam associatedRAM at the TCAM location, location
+ *
+ * Input:
+ * location tcam associatedRAM location
+ * ram_data Value to write
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_tcam_asc_ram_entry_write(npi_handle_t,
+ tcam_location_t,
+ uint64_t);
+
+
+/*
+ * npi_fflp_tcam_asc_ram_entry_read()
+ *
+ * reads a tcam associatedRAM content at the TCAM location, location
+ *
+ * Input:
+ * location tcam associatedRAM location
+ * ram_data ptr to return contents
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_fflp_tcam_asc_ram_entry_read(npi_handle_t,
+ tcam_location_t,
+ uint64_t *);
+
+/*
+ * npi_fflp_tcam_get_err_log
+ * Reports TCAM PIO read and lookup errors.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various TCAM errors.
+ * will be updated if there are TCAM errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t npi_fflp_tcam_get_err_log(npi_handle_t, tcam_err_log_t *);
+
+
+
+/*
+ * npi_fflp_tcam_clr_err_log
+ * Clears TCAM PIO read and lookup error status.
+ * If there are TCAM errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various TCAM errors.
+ * will be updated if there are TCAM errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t npi_fflp_tcam_clr_err_log(npi_handle_t);
+
+
+
+
+
+/*
+ * npi_fflp_vlan_tbl_clr_err_log
+ * Clears VLAN Table PIO error status.
+ * If there are VLAN Table errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various VLAN Table errors.
+ * will be updated if there are errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+
+npi_status_t npi_fflp_vlan_tbl_clr_err_log(npi_handle_t);
+
+
+/*
+ * npi_fflp_vlan_tbl_get_err_log
+ * Reports VLAN Table errors.
+ * If there are VLAN Table errors as indicated by err bit set by HW,
+ * then the SW will clear it by clearing the bit.
+ *
+ * Input
+ * err_stat: structure to report various VLAN table errors.
+ * will be updated if there are errors.
+ *
+ *
+ * Return
+ * NPI_SUCCESS Success
+ *
+ *
+ */
+npi_status_t npi_fflp_vlan_tbl_get_err_log(npi_handle_t,
+ vlan_tbl_err_log_t *);
+
+
+
+
+/*
+ * npi_rxdma_event_mask_config():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cfgp - pointer to NPI defined event mask
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR
+ *
+ */
+npi_status_t
+npi_fflp_event_mask_config(npi_handle_t, io_op_t,
+ fflp_event_mask_cfg_t *);
+
+npi_status_t npi_fflp_dump_regs(npi_handle_t);
+
+
+/* Error status read and clear functions */
+
+void npi_fflp_vlan_error_get(npi_handle_t,
+ p_vlan_par_err_t);
+void npi_fflp_vlan_error_clear(npi_handle_t);
+void npi_fflp_tcam_error_get(npi_handle_t,
+ p_tcam_err_t);
+void npi_fflp_tcam_error_clear(npi_handle_t);
+
+void npi_fflp_fcram_error_get(npi_handle_t,
+ p_hash_tbl_data_log_t,
+ uint8_t);
+void npi_fflp_fcram_error_clear(npi_handle_t, uint8_t);
+
+void npi_fflp_fcram_error_log1_get(npi_handle_t,
+ p_hash_lookup_err_log1_t);
+
+void npi_fflp_fcram_error_log2_get(npi_handle_t,
+ p_hash_lookup_err_log2_t);
+
+void npi_fflp_vlan_tbl_dump(npi_handle_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_FFLP_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.c b/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.c
new file mode 100644
index 0000000000..4ab1ee5afa
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.c
@@ -0,0 +1,686 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_ipp.h>
+
+uint64_t ipp_fzc_offset[] = {
+ IPP_CONFIG_REG,
+ IPP_DISCARD_PKT_CNT_REG,
+ IPP_TCP_CKSUM_ERR_CNT_REG,
+ IPP_ECC_ERR_COUNTER_REG,
+ IPP_INT_STATUS_REG,
+ IPP_INT_MASK_REG,
+ IPP_PFIFO_RD_DATA0_REG,
+ IPP_PFIFO_RD_DATA1_REG,
+ IPP_PFIFO_RD_DATA2_REG,
+ IPP_PFIFO_RD_DATA3_REG,
+ IPP_PFIFO_RD_DATA4_REG,
+ IPP_PFIFO_WR_DATA0_REG,
+ IPP_PFIFO_WR_DATA1_REG,
+ IPP_PFIFO_WR_DATA2_REG,
+ IPP_PFIFO_WR_DATA3_REG,
+ IPP_PFIFO_WR_DATA4_REG,
+ IPP_PFIFO_RD_PTR_REG,
+ IPP_PFIFO_WR_PTR_REG,
+ IPP_DFIFO_RD_DATA0_REG,
+ IPP_DFIFO_RD_DATA1_REG,
+ IPP_DFIFO_RD_DATA2_REG,
+ IPP_DFIFO_RD_DATA3_REG,
+ IPP_DFIFO_RD_DATA4_REG,
+ IPP_DFIFO_WR_DATA0_REG,
+ IPP_DFIFO_WR_DATA1_REG,
+ IPP_DFIFO_WR_DATA2_REG,
+ IPP_DFIFO_WR_DATA3_REG,
+ IPP_DFIFO_WR_DATA4_REG,
+ IPP_DFIFO_RD_PTR_REG,
+ IPP_DFIFO_WR_PTR_REG,
+ IPP_STATE_MACHINE_REG,
+ IPP_CKSUM_STATUS_REG,
+ IPP_FFLP_CKSUM_INFO_REG,
+ IPP_DEBUG_SELECT_REG,
+ IPP_DFIFO_ECC_SYNDROME_REG,
+ IPP_DFIFO_EOPM_RD_PTR_REG,
+ IPP_ECC_CTRL_REG
+};
+
+const char *ipp_fzc_name[] = {
+ "IPP_CONFIG_REG",
+ "IPP_DISCARD_PKT_CNT_REG",
+ "IPP_TCP_CKSUM_ERR_CNT_REG",
+ "IPP_ECC_ERR_COUNTER_REG",
+ "IPP_INT_STATUS_REG",
+ "IPP_INT_MASK_REG",
+ "IPP_PFIFO_RD_DATA0_REG",
+ "IPP_PFIFO_RD_DATA1_REG",
+ "IPP_PFIFO_RD_DATA2_REG",
+ "IPP_PFIFO_RD_DATA3_REG",
+ "IPP_PFIFO_RD_DATA4_REG",
+ "IPP_PFIFO_WR_DATA0_REG",
+ "IPP_PFIFO_WR_DATA1_REG",
+ "IPP_PFIFO_WR_DATA2_REG",
+ "IPP_PFIFO_WR_DATA3_REG",
+ "IPP_PFIFO_WR_DATA4_REG",
+ "IPP_PFIFO_RD_PTR_REG",
+ "IPP_PFIFO_WR_PTR_REG",
+ "IPP_DFIFO_RD_DATA0_REG",
+ "IPP_DFIFO_RD_DATA1_REG",
+ "IPP_DFIFO_RD_DATA2_REG",
+ "IPP_DFIFO_RD_DATA3_REG",
+ "IPP_DFIFO_RD_DATA4_REG",
+ "IPP_DFIFO_WR_DATA0_REG",
+ "IPP_DFIFO_WR_DATA1_REG",
+ "IPP_DFIFO_WR_DATA2_REG",
+ "IPP_DFIFO_WR_DATA3_REG",
+ "IPP_DFIFO_WR_DATA4_REG",
+ "IPP_DFIFO_RD_PTR_REG",
+ "IPP_DFIFO_WR_PTR_REG",
+ "IPP_STATE_MACHINE_REG",
+ "IPP_CKSUM_STATUS_REG",
+ "IPP_FFLP_CKSUM_INFO_REG",
+ "IPP_DEBUG_SELECT_REG",
+ "IPP_DFIFO_ECC_SYNDROME_REG",
+ "IPP_DFIFO_EOPM_RD_PTR_REG",
+ "IPP_ECC_CTRL_REG",
+};
+
+npi_status_t
+npi_ipp_dump_regs(npi_handle_t handle, uint8_t port)
+{
+ uint64_t value, offset;
+ int num_regs, i;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_dump_regs"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE);
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nIPP PORT Register Dump for port %d\n", port));
+
+ num_regs = sizeof (ipp_fzc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ offset = IPP_REG_ADDR(port, ipp_fzc_offset[i]);
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ offset, ipp_fzc_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n IPP FZC Register Dump for port %d done\n", port));
+
+ return (NPI_SUCCESS);
+}
+
+void
+npi_ipp_read_regs(npi_handle_t handle, uint8_t port)
+{
+ uint64_t value, offset;
+ int num_regs, i;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_dump_regs"
+ " Invalid Input: port <%d>", port));
+ return;
+ }
+
+ NPI_DEBUG_MSG((handle.function, NPI_IPP_CTL,
+ "\nIPP PORT Register read (to clear) for port %d\n", port));
+
+ num_regs = sizeof (ipp_fzc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ offset = IPP_REG_ADDR(port, ipp_fzc_offset[i]);
+ NXGE_REG_RD64(handle, offset, &value);
+ }
+
+}
+
+/* IPP Reset Routine */
+
+npi_status_t
+npi_ipp_reset(npi_handle_t handle, uint8_t portn)
+{
+ uint64_t val = 0;
+ uint32_t cnt = MAX_PIO_RETRIES;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_reset"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+ val |= IPP_SOFT_RESET;
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ do {
+ NXGE_DELAY(IPP_RESET_WAIT);
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+ cnt--;
+ } while (((val & IPP_SOFT_RESET) != 0) && (cnt > 0));
+
+ if (cnt == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_reset"
+ " HW Error: IPP_RESET <0x%x>", val));
+ return (NPI_FAILURE | NPI_IPP_RESET_FAILED(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/* IPP Configuration Routine */
+
+npi_status_t
+npi_ipp_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ ipp_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_config"
+ " Invalid Input portn <0x%x>", portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || ((config & ~CFG_IPP_ALL) != 0)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_config",
+ " Invalid Input config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+
+ if (op == ENABLE)
+ val |= config;
+ else
+ val &= ~config;
+ break;
+
+ case INIT:
+ if ((config & ~CFG_IPP_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_config"
+ " Invalid Input config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn));
+ }
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+
+
+ val &= (IPP_IP_MAX_PKT_BYTES_MASK);
+ val |= config;
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_config"
+ " Invalid Input op <0x%x>", op));
+ return (NPI_FAILURE | NPI_IPP_OPCODE_INVALID(portn));
+ }
+
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_ipp_set_max_pktsize(npi_handle_t handle, uint8_t portn, uint32_t bytes)
+{
+ uint64_t val = 0;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_set_max_pktsize"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ if (bytes > IPP_IP_MAX_PKT_BYTES_MASK) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_set_max_pktsize"
+ " Invalid Input Max bytes <0x%x>",
+ bytes));
+ return (NPI_FAILURE | NPI_IPP_MAX_PKT_BYTES_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+ val &= ~(IPP_IP_MAX_PKT_BYTES_MASK << IPP_IP_MAX_PKT_BYTES_SHIFT);
+
+ val |= (bytes << IPP_IP_MAX_PKT_BYTES_SHIFT);
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/* IPP Interrupt Configuration Routine */
+
+npi_status_t
+npi_ipp_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ ipp_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_config"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || ((iconfig & ~ICFG_IPP_ALL) != 0)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_iconfig"
+ " Invalid Input iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_INT_MASK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ IPP_REG_WR(handle, portn, IPP_INT_MASK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_IPP_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_iconfig"
+ " Invalid Input iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_IPP_CONFIG_INVALID(portn));
+ }
+ IPP_REG_WR(handle, portn, IPP_INT_MASK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_iconfig"
+ " Invalid Input iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_IPP_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_status(npi_handle_t handle, uint8_t portn, ipp_status_t *status)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_status"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_INT_STATUS_REG, &val);
+
+ status->value = val;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_pfifo_rd_ptr(npi_handle_t handle, uint8_t portn, uint16_t *rd_ptr)
+{
+ uint64_t value;
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_pfifo_rd_ptr"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_PTR_REG, &value);
+ *rd_ptr = value & 0xfff;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_pfifo_wr_ptr(npi_handle_t handle, uint8_t portn, uint16_t *wr_ptr)
+{
+ uint64_t value;
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_pfifo_wr_ptr"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_PFIFO_WR_PTR_REG, &value);
+ *wr_ptr = value & 0xfff;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_dfifo_rd_ptr(npi_handle_t handle, uint8_t portn, uint16_t *rd_ptr)
+{
+ uint64_t value;
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_dfifo_rd_ptr"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_PTR_REG, &value);
+ *rd_ptr = (uint16_t)(value & ((portn < 2) ? IPP_XMAC_DFIFO_PTR_MASK :
+ IPP_BMAC_DFIFO_PTR_MASK));
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_dfifo_wr_ptr(npi_handle_t handle, uint8_t portn, uint16_t *wr_ptr)
+{
+ uint64_t value;
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_dfifo_wr_ptr"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_DFIFO_WR_PTR_REG, &value);
+ *wr_ptr = (uint16_t)(value & ((portn < 2) ? IPP_XMAC_DFIFO_PTR_MASK :
+ IPP_BMAC_DFIFO_PTR_MASK));
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_ipp_write_pfifo(npi_handle_t handle, uint8_t portn, uint8_t addr,
+ uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_write_pfifo"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ if (addr >= 64) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_write_pfifo"
+ " Invalid PFIFO address <0x%x>", addr));
+ return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+ val |= IPP_PRE_FIFO_PIO_WR_EN;
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_PTR_REG, addr);
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA0_REG, d0);
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA1_REG, d1);
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA2_REG, d2);
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA3_REG, d3);
+ IPP_REG_WR(handle, portn, IPP_PFIFO_WR_DATA4_REG, d4);
+
+ val &= ~IPP_PRE_FIFO_PIO_WR_EN;
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_read_pfifo(npi_handle_t handle, uint8_t portn, uint8_t addr,
+ uint32_t *d0, uint32_t *d1, uint32_t *d2, uint32_t *d3,
+ uint32_t *d4)
+{
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_read_pfifo"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ if (addr >= 64) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_read_pfifo"
+ " Invalid PFIFO address <0x%x>", addr));
+ return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn));
+ }
+
+ IPP_REG_WR(handle, portn, IPP_PFIFO_RD_PTR_REG, addr);
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA0_REG, d0);
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA1_REG, d1);
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA2_REG, d2);
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA3_REG, d3);
+ IPP_REG_RD(handle, portn, IPP_PFIFO_RD_DATA4_REG, d4);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_write_dfifo(npi_handle_t handle, uint8_t portn, uint16_t addr,
+ uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_write_dfifo"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ if (addr >= 2048) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_write_dfifo"
+ " Invalid DFIFO address <0x%x>", addr));
+ return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_CONFIG_REG, &val);
+ val |= IPP_DFIFO_PIO_WR_EN;
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_PTR_REG, addr);
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA0_REG, d0);
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA1_REG, d1);
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA2_REG, d2);
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA3_REG, d3);
+ IPP_REG_WR(handle, portn, IPP_DFIFO_WR_DATA4_REG, d4);
+
+ val &= ~IPP_DFIFO_PIO_WR_EN;
+ IPP_REG_WR(handle, portn, IPP_CONFIG_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_read_dfifo(npi_handle_t handle, uint8_t portn, uint16_t addr,
+ uint32_t *d0, uint32_t *d1, uint32_t *d2, uint32_t *d3,
+ uint32_t *d4)
+{
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_read_dfifo"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ if (addr >= 2048) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_read_dfifo"
+ " Invalid DFIFO address <0x%x>", addr));
+ return (NPI_FAILURE | NPI_IPP_FIFO_ADDR_INVALID(portn));
+ }
+
+ IPP_REG_WR(handle, portn, IPP_DFIFO_RD_PTR_REG, addr);
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA0_REG, d0);
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA1_REG, d1);
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA2_REG, d2);
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA3_REG, d3);
+ IPP_REG_RD(handle, portn, IPP_DFIFO_RD_DATA4_REG, d4);
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_ipp_get_ecc_syndrome(npi_handle_t handle, uint8_t portn, uint16_t *syndrome)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_ecc_syndrome"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_DFIFO_ECC_SYNDROME_REG, &val);
+
+ *syndrome = (uint16_t)val;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_dfifo_eopm_rdptr(npi_handle_t handle, uint8_t portn,
+ uint16_t *rdptr)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_dfifo_rdptr"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_DFIFO_EOPM_RD_PTR_REG, &val);
+
+ *rdptr = (uint16_t)val;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_state_mach(npi_handle_t handle, uint8_t portn, uint32_t *sm)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_state_mach"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_STATE_MACHINE_REG, &val);
+
+ *sm = (uint32_t)val;
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_ecc_err_count(npi_handle_t handle, uint8_t portn, uint8_t *err_cnt)
+{
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_ecc_err_count"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_ECC_ERR_COUNTER_REG, err_cnt);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_pkt_dis_count(npi_handle_t handle, uint8_t portn, uint16_t *dis_cnt)
+{
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_pkt_dis_count"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_DISCARD_PKT_CNT_REG, dis_cnt);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_ipp_get_cs_err_count(npi_handle_t handle, uint8_t portn, uint16_t *err_cnt)
+{
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ipp_get_cs_err_count"
+ " Invalid Input portn <0x%x>",
+ portn));
+ return (NPI_FAILURE | NPI_IPP_PORT_INVALID(portn));
+ }
+
+ IPP_REG_RD(handle, portn, IPP_ECC_ERR_COUNTER_REG, err_cnt);
+
+ return (NPI_SUCCESS);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.h b/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.h
new file mode 100644
index 0000000000..b3685e063e
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_ipp.h
@@ -0,0 +1,188 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_IPP_H
+#define _NPI_IPP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_ipp_hw.h>
+
+/* IBTP IPP Configuration */
+
+typedef enum ipp_config_e {
+ CFG_IPP = IPP_EN,
+ CFG_IPP_DFIFO_ECC_CORRECT = IPP_DFIFO_ECC_CORRECT_EN,
+ CFG_IPP_DROP_BAD_CRC = IPP_DROP_BAD_CRC_EN,
+ CFG_IPP_TCP_UDP_CKSUM = IPP_TCP_UDP_CKSUM_EN,
+ CFG_IPP_DFIFO_PIO_WR = IPP_DFIFO_PIO_WR_EN,
+ CFG_IPP_PRE_FIFO_PIO_WR = IPP_PRE_FIFO_PIO_WR_EN,
+ CFG_IPP_FFLP_CKSUM_INFO_PIO_WR = IPP_FFLP_CKSUM_INFO_PIO_WR_EN,
+ CFG_IPP_ALL = (IPP_EN | IPP_DFIFO_ECC_CORRECT_EN |
+ IPP_DROP_BAD_CRC_EN | IPP_TCP_UDP_CKSUM_EN |
+ IPP_DFIFO_PIO_WR_EN | IPP_PRE_FIFO_PIO_WR_EN)
+} ipp_config_t;
+
+typedef enum ipp_iconfig_e {
+ ICFG_IPP_PKT_DISCARD_OVFL = IPP_PKT_DISCARD_CNT_INTR_DIS,
+ ICFG_IPP_BAD_TCPIP_CKSUM_OVFL = IPP_BAD_TCPIP_CKSUM_CNT_INTR_DIS,
+ ICFG_IPP_PRE_FIFO_UNDERRUN = IPP_PRE_FIFO_UNDERRUN_INTR_DIS,
+ ICFG_IPP_PRE_FIFO_OVERRUN = IPP_PRE_FIFO_OVERRUN_INTR_DIS,
+ ICFG_IPP_PRE_FIFO_PERR = IPP_PRE_FIFO_PERR_INTR_DIS,
+ ICFG_IPP_DFIFO_ECC_UNCORR_ERR = IPP_DFIFO_ECC_UNCORR_ERR_INTR_DIS,
+ ICFG_IPP_DFIFO_MISSING_EOP_SOP = IPP_DFIFO_MISSING_EOP_SOP_INTR_DIS,
+ ICFG_IPP_ECC_ERR_OVFL = IPP_ECC_ERR_CNT_MAX_INTR_DIS,
+ ICFG_IPP_ALL = (IPP_PKT_DISCARD_CNT_INTR_DIS |
+ IPP_BAD_TCPIP_CKSUM_CNT_INTR_DIS |
+ IPP_PRE_FIFO_UNDERRUN_INTR_DIS |
+ IPP_PRE_FIFO_OVERRUN_INTR_DIS |
+ IPP_PRE_FIFO_PERR_INTR_DIS |
+ IPP_DFIFO_ECC_UNCORR_ERR_INTR_DIS |
+ IPP_DFIFO_MISSING_EOP_SOP_INTR_DIS |
+ IPP_ECC_ERR_CNT_MAX_INTR_DIS)
+} ipp_iconfig_t;
+
+typedef enum ipp_counter_e {
+ CNT_IPP_DISCARD_PKT = 0x00000001,
+ CNT_IPP_TCP_CKSUM_ERR = 0x00000002,
+ CNT_IPP_ECC_ERR = 0x00000004,
+ CNT_IPP_ALL = 0x00000007
+} ipp_counter_t;
+
+
+typedef enum ipp_port_cnt_idx_e {
+ HWCI_IPP_PKT_DISCARD = 0,
+ HWCI_IPP_TCP_CKSUM_ERR,
+ HWCI_IPP_ECC_ERR,
+ CI_IPP_MISSING_EOP_SOP,
+ CI_IPP_UNCORR_ERR,
+ CI_IPP_PERR,
+ CI_IPP_FIFO_OVERRUN,
+ CI_IPP_FIFO_UNDERRUN,
+ CI_IPP_PORT_CNT_ARR_SIZE
+} ipp_port_cnt_idx_t;
+
+/* IPP specific errors */
+
+#define IPP_MAX_PKT_BYTES_INVALID 0x50
+#define IPP_FIFO_ADDR_INVALID 0x51
+
+/* IPP error return macros */
+
+#define NPI_IPP_PORT_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) | PORT_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_OPCODE_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) | OPCODE_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_CONFIG_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) | CONFIG_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_MAX_PKT_BYTES_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ IPP_MAX_PKT_BYTES_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_COUNTER_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) | COUNTER_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_RESET_FAILED(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) | RESET_FAILED |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+#define NPI_IPP_FIFO_ADDR_INVALID(portn)\
+ ((IPP_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ IPP_FIFO_ADDR_INVALID |\
+ IS_PORT | (portn << NPI_PORT_CHAN_SHIFT))
+
+#define IPP_REG_RD(handle, portn, reg, val) {\
+ NXGE_REG_RD64(handle, IPP_REG_ADDR(portn, reg), val);\
+}
+
+#define IPP_REG_WR(handle, portn, reg, val) {\
+ NXGE_REG_WR64(handle, IPP_REG_ADDR(portn, reg), val);\
+}
+
+/* IPP NPI function prototypes */
+npi_status_t npi_ipp_get_pfifo_rd_ptr(npi_handle_t, uint8_t,
+ uint16_t *);
+
+npi_status_t npi_ipp_get_pfifo_wr_ptr(npi_handle_t, uint8_t,
+ uint16_t *);
+
+npi_status_t npi_ipp_write_pfifo(npi_handle_t, uint8_t,
+ uint8_t, uint32_t, uint32_t, uint32_t,
+ uint32_t, uint32_t);
+
+npi_status_t npi_ipp_read_pfifo(npi_handle_t, uint8_t,
+ uint8_t, uint32_t *, uint32_t *, uint32_t *,
+ uint32_t *, uint32_t *);
+
+npi_status_t npi_ipp_write_dfifo(npi_handle_t, uint8_t,
+ uint16_t, uint32_t, uint32_t, uint32_t,
+ uint32_t, uint32_t);
+
+npi_status_t npi_ipp_read_dfifo(npi_handle_t, uint8_t,
+ uint16_t, uint32_t *, uint32_t *, uint32_t *,
+ uint32_t *, uint32_t *);
+
+npi_status_t npi_ipp_reset(npi_handle_t, uint8_t);
+npi_status_t npi_ipp_config(npi_handle_t, config_op_t, uint8_t,
+ ipp_config_t);
+npi_status_t npi_ipp_set_max_pktsize(npi_handle_t, uint8_t,
+ uint32_t);
+npi_status_t npi_ipp_iconfig(npi_handle_t, config_op_t, uint8_t,
+ ipp_iconfig_t);
+npi_status_t npi_ipp_get_status(npi_handle_t, uint8_t,
+ ipp_status_t *);
+npi_status_t npi_ipp_counters(npi_handle_t, counter_op_t,
+ ipp_counter_t, uint8_t, npi_counter_t *);
+npi_status_t npi_ipp_get_ecc_syndrome(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_get_dfifo_eopm_rdptr(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_get_state_mach(npi_handle_t, uint8_t,
+ uint32_t *);
+npi_status_t npi_ipp_get_dfifo_rd_ptr(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_get_dfifo_wr_ptr(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_get_ecc_err_count(npi_handle_t, uint8_t,
+ uint8_t *);
+npi_status_t npi_ipp_get_pkt_dis_count(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_get_cs_err_count(npi_handle_t, uint8_t,
+ uint16_t *);
+npi_status_t npi_ipp_dump_regs(npi_handle_t, uint8_t);
+void npi_ipp_read_regs(npi_handle_t, uint8_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_IPP_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_mac.c b/usr/src/uts/sun4v/io/nxge/npi/npi_mac.c
new file mode 100644
index 0000000000..f3ba7dddc0
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_mac.c
@@ -0,0 +1,3765 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_mac.h>
+
+#define XMAC_WAIT_REG(handle, portn, reg, val) {\
+ uint32_t cnt = MAX_PIO_RETRIES;\
+ do {\
+ NXGE_DELAY(MAC_RESET_WAIT);\
+ XMAC_REG_RD(handle, portn, reg, &val);\
+ cnt--;\
+ } while (((val & 0x3) != 0) && (cnt > 0));\
+}
+
+#define BMAC_WAIT_REG(handle, portn, reg, val) {\
+ uint32_t cnt = MAX_PIO_RETRIES;\
+ do {\
+ NXGE_DELAY(MAC_RESET_WAIT);\
+ BMAC_REG_RD(handle, portn, reg, &val);\
+ cnt--;\
+ } while (((val & 0x3) != 0) && (cnt > 0));\
+}
+
+uint64_t xmac_offset[] = {
+ XTXMAC_SW_RST_REG,
+ XRXMAC_SW_RST_REG,
+ XTXMAC_STATUS_REG,
+ XRXMAC_STATUS_REG,
+ XMAC_CTRL_STAT_REG,
+ XTXMAC_STAT_MSK_REG,
+ XRXMAC_STAT_MSK_REG,
+ XMAC_C_S_MSK_REG,
+ XMAC_CONFIG_REG,
+ XMAC_IPG_REG,
+ XMAC_MIN_REG,
+ XMAC_MAX_REG,
+ XMAC_ADDR0_REG,
+ XMAC_ADDR1_REG,
+ XMAC_ADDR2_REG,
+ XRXMAC_BT_CNT_REG,
+ XRXMAC_BC_FRM_CNT_REG,
+ XRXMAC_MC_FRM_CNT_REG,
+ XRXMAC_FRAG_CNT_REG,
+ XRXMAC_HIST_CNT1_REG,
+ XRXMAC_HIST_CNT2_REG,
+ XRXMAC_HIST_CNT3_REG,
+ XRXMAC_HIST_CNT4_REG,
+ XRXMAC_HIST_CNT5_REG,
+ XRXMAC_HIST_CNT6_REG,
+ XRXMAC_MPSZER_CNT_REG,
+ XRXMAC_CRC_ER_CNT_REG,
+ XRXMAC_CD_VIO_CNT_REG,
+ XRXMAC_AL_ER_CNT_REG,
+ XTXMAC_FRM_CNT_REG,
+ XTXMAC_BYTE_CNT_REG,
+ XMAC_LINK_FLT_CNT_REG,
+ XRXMAC_HIST_CNT7_REG,
+ XMAC_SM_REG,
+ XMAC_INTERN1_REG,
+ XMAC_ADDR_CMPEN_REG,
+ XMAC_ADDR3_REG,
+ XMAC_ADDR4_REG,
+ XMAC_ADDR5_REG,
+ XMAC_ADDR6_REG,
+ XMAC_ADDR7_REG,
+ XMAC_ADDR8_REG,
+ XMAC_ADDR9_REG,
+ XMAC_ADDR10_REG,
+ XMAC_ADDR11_REG,
+ XMAC_ADDR12_REG,
+ XMAC_ADDR13_REG,
+ XMAC_ADDR14_REG,
+ XMAC_ADDR15_REG,
+ XMAC_ADDR16_REG,
+ XMAC_ADDR17_REG,
+ XMAC_ADDR18_REG,
+ XMAC_ADDR19_REG,
+ XMAC_ADDR20_REG,
+ XMAC_ADDR21_REG,
+ XMAC_ADDR22_REG,
+ XMAC_ADDR23_REG,
+ XMAC_ADDR24_REG,
+ XMAC_ADDR25_REG,
+ XMAC_ADDR26_REG,
+ XMAC_ADDR27_REG,
+ XMAC_ADDR28_REG,
+ XMAC_ADDR29_REG,
+ XMAC_ADDR30_REG,
+ XMAC_ADDR31_REG,
+ XMAC_ADDR32_REG,
+ XMAC_ADDR33_REG,
+ XMAC_ADDR34_REG,
+ XMAC_ADDR35_REG,
+ XMAC_ADDR36_REG,
+ XMAC_ADDR37_REG,
+ XMAC_ADDR38_REG,
+ XMAC_ADDR39_REG,
+ XMAC_ADDR40_REG,
+ XMAC_ADDR41_REG,
+ XMAC_ADDR42_REG,
+ XMAC_ADDR43_REG,
+ XMAC_ADDR44_REG,
+ XMAC_ADDR45_REG,
+ XMAC_ADDR46_REG,
+ XMAC_ADDR47_REG,
+ XMAC_ADDR48_REG,
+ XMAC_ADDR49_REG,
+ XMAC_ADDR50_REG,
+ XMAC_ADDR_FILT0_REG,
+ XMAC_ADDR_FILT1_REG,
+ XMAC_ADDR_FILT2_REG,
+ XMAC_ADDR_FILT12_MASK_REG,
+ XMAC_ADDR_FILT0_MASK_REG,
+ XMAC_HASH_TBL0_REG,
+ XMAC_HASH_TBL1_REG,
+ XMAC_HASH_TBL2_REG,
+ XMAC_HASH_TBL3_REG,
+ XMAC_HASH_TBL4_REG,
+ XMAC_HASH_TBL5_REG,
+ XMAC_HASH_TBL6_REG,
+ XMAC_HASH_TBL7_REG,
+ XMAC_HASH_TBL8_REG,
+ XMAC_HASH_TBL9_REG,
+ XMAC_HASH_TBL10_REG,
+ XMAC_HASH_TBL11_REG,
+ XMAC_HASH_TBL12_REG,
+ XMAC_HASH_TBL13_REG,
+ XMAC_HASH_TBL14_REG,
+ XMAC_HASH_TBL15_REG,
+ XMAC_HOST_INF0_REG,
+ XMAC_HOST_INF1_REG,
+ XMAC_HOST_INF2_REG,
+ XMAC_HOST_INF3_REG,
+ XMAC_HOST_INF4_REG,
+ XMAC_HOST_INF5_REG,
+ XMAC_HOST_INF6_REG,
+ XMAC_HOST_INF7_REG,
+ XMAC_HOST_INF8_REG,
+ XMAC_HOST_INF9_REG,
+ XMAC_HOST_INF10_REG,
+ XMAC_HOST_INF11_REG,
+ XMAC_HOST_INF12_REG,
+ XMAC_HOST_INF13_REG,
+ XMAC_HOST_INF14_REG,
+ XMAC_HOST_INF15_REG,
+ XMAC_HOST_INF16_REG,
+ XMAC_HOST_INF17_REG,
+ XMAC_HOST_INF18_REG,
+ XMAC_HOST_INF19_REG,
+ XMAC_PA_DATA0_REG,
+ XMAC_PA_DATA1_REG,
+ XMAC_DEBUG_SEL_REG,
+ XMAC_TRAINING_VECT_REG,
+};
+
+const char *xmac_name[] = {
+ "XTXMAC_SW_RST_REG",
+ "XRXMAC_SW_RST_REG",
+ "XTXMAC_STATUS_REG",
+ "XRXMAC_STATUS_REG",
+ "XMAC_CTRL_STAT_REG",
+ "XTXMAC_STAT_MSK_REG",
+ "XRXMAC_STAT_MSK_REG",
+ "XMAC_C_S_MSK_REG",
+ "XMAC_CONFIG_REG",
+ "XMAC_IPG_REG",
+ "XMAC_MIN_REG",
+ "XMAC_MAX_REG",
+ "XMAC_ADDR0_REG",
+ "XMAC_ADDR1_REG",
+ "XMAC_ADDR2_REG",
+ "XRXMAC_BT_CNT_REG",
+ "XRXMAC_BC_FRM_CNT_REG",
+ "XRXMAC_MC_FRM_CNT_REG",
+ "XRXMAC_FRAG_CNT_REG",
+ "XRXMAC_HIST_CNT1_REG",
+ "XRXMAC_HIST_CNT2_REG",
+ "XRXMAC_HIST_CNT3_REG",
+ "XRXMAC_HIST_CNT4_REG",
+ "XRXMAC_HIST_CNT5_REG",
+ "XRXMAC_HIST_CNT6_REG",
+ "XRXMAC_MPSZER_CNT_REG",
+ "XRXMAC_CRC_ER_CNT_REG",
+ "XRXMAC_CD_VIO_CNT_REG",
+ "XRXMAC_AL_ER_CNT_REG",
+ "XTXMAC_FRM_CNT_REG",
+ "XTXMAC_BYTE_CNT_REG",
+ "XMAC_LINK_FLT_CNT_REG",
+ "XRXMAC_HIST_CNT7_REG",
+ "XMAC_SM_REG",
+ "XMAC_INTERN1_REG",
+ "XMAC_ADDR_CMPEN_REG",
+ "XMAC_ADDR3_REG",
+ "XMAC_ADDR4_REG",
+ "XMAC_ADDR5_REG",
+ "XMAC_ADDR6_REG",
+ "XMAC_ADDR7_REG",
+ "XMAC_ADDR8_REG",
+ "XMAC_ADDR9_REG",
+ "XMAC_ADDR10_REG",
+ "XMAC_ADDR11_REG",
+ "XMAC_ADDR12_REG",
+ "XMAC_ADDR13_REG",
+ "XMAC_ADDR14_REG",
+ "XMAC_ADDR15_REG",
+ "XMAC_ADDR16_REG",
+ "XMAC_ADDR17_REG",
+ "XMAC_ADDR18_REG",
+ "XMAC_ADDR19_REG",
+ "XMAC_ADDR20_REG",
+ "XMAC_ADDR21_REG",
+ "XMAC_ADDR22_REG",
+ "XMAC_ADDR23_REG",
+ "XMAC_ADDR24_REG",
+ "XMAC_ADDR25_REG",
+ "XMAC_ADDR26_REG",
+ "XMAC_ADDR27_REG",
+ "XMAC_ADDR28_REG",
+ "XMAC_ADDR29_REG",
+ "XMAC_ADDR30_REG",
+ "XMAC_ADDR31_REG",
+ "XMAC_ADDR32_REG",
+ "XMAC_ADDR33_REG",
+ "XMAC_ADDR34_REG",
+ "XMAC_ADDR35_REG",
+ "XMAC_ADDR36_REG",
+ "XMAC_ADDR37_REG",
+ "XMAC_ADDR38_REG",
+ "XMAC_ADDR39_REG",
+ "XMAC_ADDR40_REG",
+ "XMAC_ADDR41_REG",
+ "XMAC_ADDR42_REG",
+ "XMAC_ADDR43_REG",
+ "XMAC_ADDR44_REG",
+ "XMAC_ADDR45_REG",
+ "XMAC_ADDR46_REG",
+ "XMAC_ADDR47_REG",
+ "XMAC_ADDR48_REG",
+ "XMAC_ADDR49_REG",
+ "XMAC_ADDR50_RE",
+ "XMAC_ADDR_FILT0_REG",
+ "XMAC_ADDR_FILT1_REG",
+ "XMAC_ADDR_FILT2_REG",
+ "XMAC_ADDR_FILT12_MASK_REG",
+ "XMAC_ADDR_FILT0_MASK_REG",
+ "XMAC_HASH_TBL0_REG",
+ "XMAC_HASH_TBL1_REG",
+ "XMAC_HASH_TBL2_REG",
+ "XMAC_HASH_TBL3_REG",
+ "XMAC_HASH_TBL4_REG",
+ "XMAC_HASH_TBL5_REG",
+ "XMAC_HASH_TBL6_REG",
+ "XMAC_HASH_TBL7_REG",
+ "XMAC_HASH_TBL8_REG",
+ "XMAC_HASH_TBL9_REG",
+ "XMAC_HASH_TBL10_REG",
+ "XMAC_HASH_TBL11_REG",
+ "XMAC_HASH_TBL12_REG",
+ "XMAC_HASH_TBL13_REG",
+ "XMAC_HASH_TBL14_REG",
+ "XMAC_HASH_TBL15_REG",
+ "XMAC_HOST_INF0_REG",
+ "XMAC_HOST_INF1_REG",
+ "XMAC_HOST_INF2_REG",
+ "XMAC_HOST_INF3_REG",
+ "XMAC_HOST_INF4_REG",
+ "XMAC_HOST_INF5_REG",
+ "XMAC_HOST_INF6_REG",
+ "XMAC_HOST_INF7_REG",
+ "XMAC_HOST_INF8_REG",
+ "XMAC_HOST_INF9_REG",
+ "XMAC_HOST_INF10_REG",
+ "XMAC_HOST_INF11_REG",
+ "XMAC_HOST_INF12_REG",
+ "XMAC_HOST_INF13_REG",
+ "XMAC_HOST_INF14_REG",
+ "XMAC_HOST_INF15_REG",
+ "XMAC_HOST_INF16_REG",
+ "XMAC_HOST_INF17_REG",
+ "XMAC_HOST_INF18_REG",
+ "XMAC_HOST_INF19_REG",
+ "XMAC_PA_DATA0_REG",
+ "XMAC_PA_DATA1_REG",
+ "XMAC_DEBUG_SEL_REG",
+ "XMAC_TRAINING_VECT_REG",
+};
+
+uint64_t bmac_offset[] = {
+ BTXMAC_SW_RST_REG,
+ BRXMAC_SW_RST_REG,
+ MAC_SEND_PAUSE_REG,
+ BTXMAC_STATUS_REG,
+ BRXMAC_STATUS_REG,
+ BMAC_CTRL_STAT_REG,
+ BTXMAC_STAT_MSK_REG,
+ BRXMAC_STAT_MSK_REG,
+ BMAC_C_S_MSK_REG,
+ TXMAC_CONFIG_REG,
+ RXMAC_CONFIG_REG,
+ MAC_CTRL_CONFIG_REG,
+ MAC_XIF_CONFIG_REG,
+ BMAC_MIN_REG,
+ BMAC_MAX_REG,
+ MAC_PA_SIZE_REG,
+ MAC_CTRL_TYPE_REG,
+ BMAC_ADDR0_REG,
+ BMAC_ADDR1_REG,
+ BMAC_ADDR2_REG,
+ BMAC_ADDR3_REG,
+ BMAC_ADDR4_REG,
+ BMAC_ADDR5_REG,
+ BMAC_ADDR6_REG,
+ BMAC_ADDR7_REG,
+ BMAC_ADDR8_REG,
+ BMAC_ADDR9_REG,
+ BMAC_ADDR10_REG,
+ BMAC_ADDR11_REG,
+ BMAC_ADDR12_REG,
+ BMAC_ADDR13_REG,
+ BMAC_ADDR14_REG,
+ BMAC_ADDR15_REG,
+ BMAC_ADDR16_REG,
+ BMAC_ADDR17_REG,
+ BMAC_ADDR18_REG,
+ BMAC_ADDR19_REG,
+ BMAC_ADDR20_REG,
+ BMAC_ADDR21_REG,
+ BMAC_ADDR22_REG,
+ BMAC_ADDR23_REG,
+ MAC_FC_ADDR0_REG,
+ MAC_FC_ADDR1_REG,
+ MAC_FC_ADDR2_REG,
+ MAC_ADDR_FILT0_REG,
+ MAC_ADDR_FILT1_REG,
+ MAC_ADDR_FILT2_REG,
+ MAC_ADDR_FILT12_MASK_REG,
+ MAC_ADDR_FILT00_MASK_REG,
+ MAC_HASH_TBL0_REG,
+ MAC_HASH_TBL1_REG,
+ MAC_HASH_TBL2_REG,
+ MAC_HASH_TBL3_REG,
+ MAC_HASH_TBL4_REG,
+ MAC_HASH_TBL5_REG,
+ MAC_HASH_TBL6_REG,
+ MAC_HASH_TBL7_REG,
+ MAC_HASH_TBL8_REG,
+ MAC_HASH_TBL9_REG,
+ MAC_HASH_TBL10_REG,
+ MAC_HASH_TBL11_REG,
+ MAC_HASH_TBL12_REG,
+ MAC_HASH_TBL13_REG,
+ MAC_HASH_TBL14_REG,
+ MAC_HASH_TBL15_REG,
+ RXMAC_FRM_CNT_REG,
+ MAC_LEN_ER_CNT_REG,
+ BMAC_AL_ER_CNT_REG,
+ BMAC_CRC_ER_CNT_REG,
+ BMAC_CD_VIO_CNT_REG,
+ BMAC_SM_REG,
+ BMAC_ALTAD_CMPEN_REG,
+ BMAC_HOST_INF0_REG,
+ BMAC_HOST_INF1_REG,
+ BMAC_HOST_INF2_REG,
+ BMAC_HOST_INF3_REG,
+ BMAC_HOST_INF4_REG,
+ BMAC_HOST_INF5_REG,
+ BMAC_HOST_INF6_REG,
+ BMAC_HOST_INF7_REG,
+ BMAC_HOST_INF8_REG,
+ BTXMAC_BYTE_CNT_REG,
+ BTXMAC_FRM_CNT_REG,
+ BRXMAC_BYTE_CNT_REG,
+};
+
+const char *bmac_name[] = {
+ "BTXMAC_SW_RST_REG",
+ "BRXMAC_SW_RST_REG",
+ "MAC_SEND_PAUSE_REG",
+ "BTXMAC_STATUS_REG",
+ "BRXMAC_STATUS_REG",
+ "BMAC_CTRL_STAT_REG",
+ "BTXMAC_STAT_MSK_REG",
+ "BRXMAC_STAT_MSK_REG",
+ "BMAC_C_S_MSK_REG",
+ "TXMAC_CONFIG_REG",
+ "RXMAC_CONFIG_REG",
+ "MAC_CTRL_CONFIG_REG",
+ "MAC_XIF_CONFIG_REG",
+ "BMAC_MIN_REG",
+ "BMAC_MAX_REG",
+ "MAC_PA_SIZE_REG",
+ "MAC_CTRL_TYPE_REG",
+ "BMAC_ADDR0_REG",
+ "BMAC_ADDR1_REG",
+ "BMAC_ADDR2_REG",
+ "BMAC_ADDR3_REG",
+ "BMAC_ADDR4_REG",
+ "BMAC_ADDR5_REG",
+ "BMAC_ADDR6_REG",
+ "BMAC_ADDR7_REG",
+ "BMAC_ADDR8_REG",
+ "BMAC_ADDR9_REG",
+ "BMAC_ADDR10_REG",
+ "BMAC_ADDR11_REG",
+ "BMAC_ADDR12_REG",
+ "BMAC_ADDR13_REG",
+ "BMAC_ADDR14_REG",
+ "BMAC_ADDR15_REG",
+ "BMAC_ADDR16_REG",
+ "BMAC_ADDR17_REG",
+ "BMAC_ADDR18_REG",
+ "BMAC_ADDR19_REG",
+ "BMAC_ADDR20_REG",
+ "BMAC_ADDR21_REG",
+ "BMAC_ADDR22_REG",
+ "BMAC_ADDR23_REG",
+ "MAC_FC_ADDR0_REG",
+ "MAC_FC_ADDR1_REG",
+ "MAC_FC_ADDR2_REG",
+ "MAC_ADDR_FILT0_REG",
+ "MAC_ADDR_FILT1_REG",
+ "MAC_ADDR_FILT2_REG",
+ "MAC_ADDR_FILT12_MASK_REG",
+ "MAC_ADDR_FILT00_MASK_REG",
+ "MAC_HASH_TBL0_REG",
+ "MAC_HASH_TBL1_REG",
+ "MAC_HASH_TBL2_REG",
+ "MAC_HASH_TBL3_REG",
+ "MAC_HASH_TBL4_REG",
+ "MAC_HASH_TBL5_REG",
+ "MAC_HASH_TBL6_REG",
+ "MAC_HASH_TBL7_REG",
+ "MAC_HASH_TBL8_REG",
+ "MAC_HASH_TBL9_REG",
+ "MAC_HASH_TBL10_REG",
+ "MAC_HASH_TBL11_REG",
+ "MAC_HASH_TBL12_REG",
+ "MAC_HASH_TBL13_REG",
+ "MAC_HASH_TBL14_REG",
+ "MAC_HASH_TBL15_REG",
+ "RXMAC_FRM_CNT_REG",
+ "MAC_LEN_ER_CNT_REG",
+ "BMAC_AL_ER_CNT_REG",
+ "BMAC_CRC_ER_CNT_REG",
+ "BMAC_CD_VIO_CNT_REG",
+ "BMAC_SM_REG",
+ "BMAC_ALTAD_CMPEN_REG",
+ "BMAC_HOST_INF0_REG",
+ "BMAC_HOST_INF1_REG",
+ "BMAC_HOST_INF2_REG",
+ "BMAC_HOST_INF3_REG",
+ "BMAC_HOST_INF4_REG",
+ "BMAC_HOST_INF5_REG",
+ "BMAC_HOST_INF6_REG",
+ "BMAC_HOST_INF7_REG",
+ "BMAC_HOST_INF8_REG",
+ "BTXMAC_BYTE_CNT_REG",
+ "BTXMAC_FRM_CNT_REG",
+ "BRXMAC_BYTE_CNT_REG",
+};
+
+npi_status_t
+npi_mac_dump_regs(npi_handle_t handle, uint8_t port)
+{
+
+ uint64_t value;
+ int num_regs, i;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_dump_regs"
+ " Invalid Input: portn <%d>",
+ port));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(port));
+ }
+
+ switch (port) {
+ case 0:
+ case 1:
+ num_regs = sizeof (xmac_offset) / sizeof (uint64_t);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nXMAC Register Dump for port %d\n",
+ port));
+ for (i = 0; i < num_regs; i++) {
+ XMAC_REG_RD(handle, port, xmac_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "%08llx %s\t %08llx \n",
+ (XMAC_REG_ADDR((port), (xmac_offset[i]))),
+ xmac_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n XMAC Register Dump for port %d done\n",
+ port));
+ break;
+
+ case 2:
+ case 3:
+ num_regs = sizeof (bmac_offset) / sizeof (uint64_t);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nBMAC Register Dump for port %d\n",
+ port));
+ for (i = 0; i < num_regs; i++) {
+ BMAC_REG_RD(handle, port, bmac_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "%08llx %s\t %08llx \n",
+ (BMAC_REG_ADDR((port), (bmac_offset[i]))),
+ bmac_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n BMAC Register Dump for port %d done\n",
+ port));
+ break;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_mac_pcs_link_intr_enable(npi_handle_t handle, uint8_t portn)
+{
+ pcs_cfg_t pcs_cfg;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_link_intr_enable"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ PCS_REG_RD(handle, portn, PCS_CONFIG_REG, &pcs_cfg.value);
+ pcs_cfg.bits.w0.mask = 0;
+ PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_pcs_link_intr_disable(npi_handle_t handle, uint8_t portn)
+{
+ pcs_cfg_t pcs_cfg;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_link_intr_disable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ PCS_REG_RD(handle, portn, PCS_CONFIG_REG, &pcs_cfg.val.lsw);
+ pcs_cfg.bits.w0.mask = 1;
+ PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.val.lsw);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_link_intr_enable(npi_handle_t handle, uint8_t portn)
+{
+ xpcs_stat1_t xpcs_mask1;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_link_intr_enable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XPCS_REG_RD(handle, portn, XPCS_MASK_1_REG, &xpcs_mask1.val.lsw);
+ xpcs_mask1.bits.w0.csr_rx_link_stat = 1;
+ XPCS_REG_WR(handle, portn, XPCS_MASK_1_REG, xpcs_mask1.val.lsw);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_link_intr_disable(npi_handle_t handle, uint8_t portn)
+{
+ xpcs_stat1_t xpcs_mask1;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_link_intr_disable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XPCS_REG_RD(handle, portn, XPCS_MASK_1_REG, &xpcs_mask1.val.lsw);
+ xpcs_mask1.bits.w0.csr_rx_link_stat = 0;
+ XPCS_REG_WR(handle, portn, XPCS_MASK_1_REG, xpcs_mask1.val.lsw);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_link_intr_disable(npi_handle_t handle, uint8_t portn)
+{
+ mif_cfg_t mif_cfg;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_mif_link_intr_disable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ MIF_REG_RD(handle, MIF_CONFIG_REG, &mif_cfg.val.lsw);
+
+ mif_cfg.bits.w0.phy_addr = portn;
+ mif_cfg.bits.w0.poll_en = 0;
+
+ MIF_REG_WR(handle, MIF_CONFIG_REG, mif_cfg.val.lsw);
+
+ NXGE_DELAY(20);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_hashtab_entry(npi_handle_t handle, io_op_t op, uint8_t portn,
+ uint8_t entryn, uint16_t *data)
+{
+ uint64_t val;
+
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hashtab_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hashtab_entry"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if (entryn >= MAC_MAX_HASH_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hashtab_entry"
+ " Invalid Input: entryn <0x%x>",
+ entryn));
+ return (NPI_FAILURE | NPI_MAC_HASHTAB_ENTRY_INVALID(portn));
+ }
+
+ if (op == OP_SET) {
+ val = *data;
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ XMAC_REG_WR(handle, portn,
+ XMAC_HASH_TBLN_REG_ADDR(entryn), val);
+ } else {
+ BMAC_REG_WR(handle, portn,
+ BMAC_HASH_TBLN_REG_ADDR(entryn), val);
+ }
+ } else {
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ XMAC_REG_RD(handle, portn,
+ XMAC_HASH_TBLN_REG_ADDR(entryn), &val);
+ } else {
+ BMAC_REG_RD(handle, portn,
+ BMAC_HASH_TBLN_REG_ADDR(entryn), &val);
+ }
+ *data = val & 0xFFFF;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_hostinfo_entry(npi_handle_t handle, io_op_t op, uint8_t portn,
+ uint8_t entryn, hostinfo_t *hostinfo)
+{
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hostinfo_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hostinfo_entry"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ if (entryn >= XMAC_MAX_HOST_INFO_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hostinfo_entry"
+ " Invalid Input: entryn <0x%x>",
+ entryn));
+ return (NPI_FAILURE |
+ NPI_MAC_HOSTINFO_ENTRY_INVALID(portn));
+ }
+ } else {
+ if (entryn >= BMAC_MAX_HOST_INFO_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_hostinfo_entry"
+ " Invalid Input: entryn <0x%x>",
+ entryn));
+ return (NPI_FAILURE |
+ NPI_MAC_HOSTINFO_ENTRY_INVALID(portn));
+ }
+ }
+
+ if (op == OP_SET) {
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ XMAC_REG_WR(handle, portn,
+ XMAC_HOST_INFN_REG_ADDR(entryn),
+ hostinfo->value);
+ } else {
+ BMAC_REG_WR(handle, portn,
+ BMAC_HOST_INFN_REG_ADDR(entryn),
+ hostinfo->value);
+ }
+ } else {
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ XMAC_REG_RD(handle, portn,
+ XMAC_HOST_INFN_REG_ADDR(entryn),
+ &hostinfo->value);
+ } else {
+ BMAC_REG_RD(handle, portn,
+ BMAC_HOST_INFN_REG_ADDR(entryn),
+ &hostinfo->value);
+ }
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_altaddr_enable(npi_handle_t handle, uint8_t portn, uint8_t addrn)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_enable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ if (addrn >= XMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_enable"
+ " Invalid Input: addrn <0x%x>",
+ addrn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_ADDR_CMPEN_REG, &val);
+ val |= (1 << addrn);
+ XMAC_REG_WR(handle, portn, XMAC_ADDR_CMPEN_REG, val);
+ } else {
+ if (addrn > BMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_enable"
+ " Invalid Input: addrn <0x%x>",
+ addrn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BMAC_ALTAD_CMPEN_REG, &val);
+ val |= (1 << addrn);
+ BMAC_REG_WR(handle, portn, BMAC_ALTAD_CMPEN_REG, val);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * While all bits of XMAC_ADDR_CMPEN_REG are for alternate MAC addresses,
+ * bit0 of BMAC_ALTAD_CMPEN_REG is for unique MAC address.
+ */
+npi_status_t
+npi_mac_altaddr_disable(npi_handle_t handle, uint8_t portn, uint8_t addrn)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_disable"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ if (addrn >= XMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_disable"
+ " Invalid Input: addrn <0x%x>",
+ addrn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_ADDR_CMPEN_REG, &val);
+ val &= ~(1 << addrn);
+ XMAC_REG_WR(handle, portn, XMAC_ADDR_CMPEN_REG, val);
+ } else {
+ if (addrn > BMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_disable"
+ " Invalid Input: addrn <0x%x>",
+ addrn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BMAC_ALTAD_CMPEN_REG, &val);
+ val &= ~(1 << addrn);
+ BMAC_REG_WR(handle, portn, BMAC_ALTAD_CMPEN_REG, val);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_altaddr_entry(npi_handle_t handle, io_op_t op, uint8_t portn,
+ uint8_t entryn, npi_mac_addr_t *data)
+{
+ uint64_t val0, val1, val2;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_entry",
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ if ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1)) {
+ if (entryn >= XMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_entry"
+ " Invalid Input: entryn <0x%x>",
+ entryn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ if (op == OP_SET) {
+ val0 = data->w0;
+ val1 = data->w1;
+ val2 = data->w2;
+ XMAC_REG_WR(handle, portn,
+ XMAC_ALT_ADDR0N_REG_ADDR(entryn), val0);
+ XMAC_REG_WR(handle, portn,
+ XMAC_ALT_ADDR1N_REG_ADDR(entryn), val1);
+ XMAC_REG_WR(handle, portn,
+ XMAC_ALT_ADDR2N_REG_ADDR(entryn), val2);
+ } else {
+ XMAC_REG_RD(handle, portn,
+ XMAC_ALT_ADDR0N_REG_ADDR(entryn), &val0);
+ XMAC_REG_RD(handle, portn,
+ XMAC_ALT_ADDR1N_REG_ADDR(entryn), &val1);
+ XMAC_REG_RD(handle, portn,
+ XMAC_ALT_ADDR2N_REG_ADDR(entryn), &val2);
+ data->w0 = val0 & 0xFFFF;
+ data->w1 = val1 & 0xFFFF;
+ data->w2 = val2 & 0xFFFF;
+ }
+ } else {
+ if (entryn >= BMAC_MAX_ALT_ADDR_ENTRY) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_altaddr_entry"
+ " Invalid Input: entryn <0x%x>",
+ entryn));
+ return (NPI_FAILURE |
+ NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn));
+ }
+ if (op == OP_SET) {
+ val0 = data->w0;
+ val1 = data->w1;
+ val2 = data->w2;
+ BMAC_REG_WR(handle, portn,
+ BMAC_ALT_ADDR0N_REG_ADDR(entryn), val0);
+ BMAC_REG_WR(handle, portn,
+ BMAC_ALT_ADDR1N_REG_ADDR(entryn), val1);
+ BMAC_REG_WR(handle, portn,
+ BMAC_ALT_ADDR2N_REG_ADDR(entryn), val2);
+ } else {
+ BMAC_REG_RD(handle, portn,
+ BMAC_ALT_ADDR0N_REG_ADDR(entryn), &val0);
+ BMAC_REG_RD(handle, portn,
+ BMAC_ALT_ADDR1N_REG_ADDR(entryn), &val1);
+ BMAC_REG_RD(handle, portn,
+ BMAC_ALT_ADDR2N_REG_ADDR(entryn), &val2);
+ data->w0 = val0 & 0xFFFF;
+ data->w1 = val1 & 0xFFFF;
+ data->w2 = val2 & 0xFFFF;
+ }
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_port_attr(npi_handle_t handle, io_op_t op, uint8_t portn,
+ npi_attr_t *attrp)
+{
+ uint64_t val = 0;
+ uint32_t attr;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if ((op != OP_GET) && (op != OP_SET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ switch (attrp->type) {
+ case MAC_PORT_MODE:
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ attr = attrp->idata[0];
+ if ((attr != MAC_MII_MODE) &&
+ (attr != MAC_GMII_MODE) &&
+ (attr != MAC_XGMII_MODE)) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " Invalid Input:"
+ " MAC_PORT_MODE <0x%x>",
+ attr));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG,
+ &val);
+ val &= ~XMAC_XIF_MII_MODE_MASK;
+ switch (attr) {
+ case MAC_MII_MODE:
+ val |= (XMAC_XIF_MII_MODE <<
+ XMAC_XIF_MII_MODE_SHIFT);
+ break;
+ case MAC_GMII_MODE:
+ val |= (XMAC_XIF_GMII_MODE <<
+ XMAC_XIF_MII_MODE_SHIFT);
+ break;
+ case MAC_XGMII_MODE:
+ val |= (XMAC_XIF_XGMII_MODE <<
+ XMAC_XIF_MII_MODE_SHIFT);
+ break;
+ default:
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG,
+ val);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG,
+ &val);
+ val &= XMAC_XIF_MII_MODE_MASK;
+ attr = val >> XMAC_XIF_MII_MODE_SHIFT;
+ attrp->odata[0] = attr;
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " Invalid Input:"
+ " MAC_PORT_MODE <0x%x>",
+ attrp->type));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ break;
+
+ case MAC_PORT_FRAME_SIZE: {
+ uint32_t min_fsize;
+ uint32_t max_fsize;
+
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ min_fsize = attrp->idata[0];
+ max_fsize = attrp->idata[1];
+ if ((min_fsize & ~XMAC_MIN_TX_FRM_SZ_MASK)
+ != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_FRAME_SIZE:"
+ " Invalid Input:"
+ " xmac_min_fsize <0x%x>",
+ min_fsize));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((max_fsize & ~XMAC_MAX_FRM_SZ_MASK)
+ != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_FRAME_SIZE:"
+ " Invalid Input:"
+ " xmac_max_fsize <0x%x>",
+ max_fsize));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_MIN_REG, &val);
+ val &= ~(XMAC_MIN_TX_FRM_SZ_MASK |
+ XMAC_MIN_RX_FRM_SZ_MASK);
+ val |= (min_fsize << XMAC_MIN_TX_FRM_SZ_SHIFT);
+ val |= (min_fsize << XMAC_MIN_RX_FRM_SZ_SHIFT);
+ XMAC_REG_WR(handle, portn, XMAC_MIN_REG, val);
+ XMAC_REG_WR(handle, portn, XMAC_MAX_REG,
+ max_fsize);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_MIN_REG, &val);
+ min_fsize = (val & XMAC_MIN_TX_FRM_SZ_MASK)
+ >> XMAC_MIN_TX_FRM_SZ_SHIFT;
+ XMAC_REG_RD(handle, portn, XMAC_MAX_REG, &val);
+ attrp->odata[0] = min_fsize;
+ attrp->odata[1] = max_fsize;
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ min_fsize = attrp->idata[0];
+ max_fsize = attrp->idata[1];
+ if ((min_fsize & ~BMAC_MIN_FRAME_MASK)
+ != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_FRAME_SIZE:"
+ " Invalid Input:"
+ " bmac_min_fsize <0x%x>",
+ min_fsize));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((max_fsize & ~BMAC_MAX_FRAME_MASK)
+ != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_FRAME_SIZE:"
+ " Invalid Input:"
+ " bmac_max_fsize <0x%x>",
+ max_fsize));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BMAC_MAX_REG, &val);
+ val &= ~BMAC_MAX_FRAME_MASK;
+ val |= max_fsize;
+ BMAC_REG_WR(handle, portn, BMAC_MAX_REG, val);
+ BMAC_REG_WR(handle, portn, BMAC_MIN_REG,
+ min_fsize);
+ } else {
+ BMAC_REG_RD(handle, portn, BMAC_MIN_REG, &val);
+ min_fsize = val & BMAC_MIN_FRAME_MASK;
+ BMAC_REG_RD(handle, portn, BMAC_MAX_REG, &val);
+ max_fsize = val & BMAC_MAX_FRAME_MASK;
+ attrp->odata[0] = min_fsize;
+ attrp->odata[1] = max_fsize;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case BMAC_PORT_MAX_BURST_SIZE: {
+ uint32_t burst_size;
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_PORT_MAX_BURST_SIZE:"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_ATTR_INVALID(portn));
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ /* NOTE: Not used in Full duplex mode */
+ if (op == OP_SET) {
+ burst_size = attrp->idata[0];
+ if ((burst_size & ~0x7FFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_MAX_BURST_SIZE:"
+ " Invalid Input:"
+ " burst_size <0x%x>",
+ burst_size));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BMAC_MAX_REG, &val);
+ val &= ~BMAC_MAX_BURST_MASK;
+ val |= (burst_size << BMAC_MAX_BURST_SHIFT);
+ BMAC_REG_WR(handle, portn, BMAC_MAX_REG, val);
+ } else {
+ BMAC_REG_RD(handle, portn, BMAC_MAX_REG, &val);
+ burst_size = (val & BMAC_MAX_BURST_MASK)
+ >> BMAC_MAX_BURST_SHIFT;
+ attrp->odata[0] = burst_size;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case BMAC_PORT_PA_SIZE: {
+ uint32_t pa_size;
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_PORT_PA_SIZE:"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_ATTR_INVALID(portn));
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ pa_size = attrp->idata[0];
+ if ((pa_size & ~0x3FF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_PORT_PA_SIZE:"
+ " Invalid Input: pa_size <0x%x>",
+ pa_size));
+
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, MAC_PA_SIZE_REG,
+ &val);
+ val &= ~BMAC_PA_SIZE_MASK;
+ val |= (pa_size << 0);
+ BMAC_REG_WR(handle, portn, MAC_PA_SIZE_REG,
+ val);
+ } else {
+ BMAC_REG_RD(handle, portn, MAC_PA_SIZE_REG,
+ &val);
+ pa_size = (val & BMAC_PA_SIZE_MASK) >> 0;
+ attrp->odata[0] = pa_size;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case BMAC_PORT_CTRL_TYPE: {
+ uint32_t ctrl_type;
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_PORT_CTRL_TYPE:"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_ATTR_INVALID(portn));
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ ctrl_type = attrp->idata[0];
+ if ((ctrl_type & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " BMAC_PORT_CTRL_TYPE:"
+ " Invalid Input:"
+ " ctrl_type <0x%x>",
+ ctrl_type));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, MAC_CTRL_TYPE_REG,
+ val);
+ } else {
+ BMAC_REG_RD(handle, portn, MAC_CTRL_TYPE_REG,
+ &val);
+ ctrl_type = (val & 0xFFFF);
+ attrp->odata[0] = ctrl_type;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case XMAC_10G_PORT_IPG:
+ {
+ uint32_t ipg0;
+
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ ipg0 = attrp->idata[0];
+
+ if ((ipg0 != XGMII_IPG_12_15) &&
+ (ipg0 != XGMII_IPG_16_19) &&
+ (ipg0 != XGMII_IPG_20_23)) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_10G_PORT_IPG:"
+ " Invalid Input:"
+ " xgmii_ipg <0x%x>",
+ ipg0));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XMAC_IPG_REG, &val);
+ val &= ~(XMAC_IPG_VALUE_MASK |
+ XMAC_IPG_VALUE1_MASK);
+
+ switch (ipg0) {
+ case XGMII_IPG_12_15:
+ val |= (IPG_12_15_BYTE <<
+ XMAC_IPG_VALUE_SHIFT);
+ break;
+ case XGMII_IPG_16_19:
+ val |= (IPG_16_19_BYTE <<
+ XMAC_IPG_VALUE_SHIFT);
+ break;
+ case XGMII_IPG_20_23:
+ val |= (IPG_20_23_BYTE <<
+ XMAC_IPG_VALUE_SHIFT);
+ break;
+ default:
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XMAC_IPG_REG, val);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_IPG_REG, &val);
+ ipg0 = (val & XMAC_IPG_VALUE_MASK) >>
+ XMAC_IPG_VALUE_SHIFT;
+ switch (ipg0) {
+ case IPG_12_15_BYTE:
+ attrp->odata[0] = XGMII_IPG_12_15;
+ break;
+ case IPG_16_19_BYTE:
+ attrp->odata[0] = XGMII_IPG_16_19;
+ break;
+ case IPG_20_23_BYTE:
+ attrp->odata[0] = XGMII_IPG_20_23;
+ break;
+ default:
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr" "MAC_PORT_IPG:"
+ " Invalid Input: portn <%d>",
+ portn));
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ break;
+ }
+
+ case XMAC_PORT_IPG:
+ {
+ uint32_t ipg1;
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ ipg1 = attrp->idata[0];
+ if ((ipg1 != MII_GMII_IPG_12) &&
+ (ipg1 != MII_GMII_IPG_13) &&
+ (ipg1 != MII_GMII_IPG_14) &&
+ (ipg1 != MII_GMII_IPG_15) &&
+ (ipg1 != MII_GMII_IPG_16)) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " XMAC_PORT_IPG:"
+ " Invalid Input:"
+ " mii_gmii_ipg <0x%x>",
+ ipg1));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XMAC_IPG_REG, &val);
+ val &= ~(XMAC_IPG_VALUE_MASK |
+ XMAC_IPG_VALUE1_MASK);
+
+ switch (ipg1) {
+ case MII_GMII_IPG_12:
+ val |= (IPG1_12_BYTES <<
+ XMAC_IPG_VALUE1_SHIFT);
+ break;
+ case MII_GMII_IPG_13:
+ val |= (IPG1_13_BYTES <<
+ XMAC_IPG_VALUE1_SHIFT);
+ break;
+ case MII_GMII_IPG_14:
+ val |= (IPG1_14_BYTES <<
+ XMAC_IPG_VALUE1_SHIFT);
+ break;
+ case MII_GMII_IPG_15:
+ val |= (IPG1_15_BYTES <<
+ XMAC_IPG_VALUE1_SHIFT);
+ break;
+ case MII_GMII_IPG_16:
+ val |= (IPG1_16_BYTES <<
+ XMAC_IPG_VALUE1_SHIFT);
+ break;
+ default:
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XMAC_IPG_REG, val);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_IPG_REG, &val);
+ ipg1 = (val & XMAC_IPG_VALUE1_MASK) >>
+ XMAC_IPG_VALUE1_SHIFT;
+ switch (ipg1) {
+ case IPG1_12_BYTES:
+ attrp->odata[1] = MII_GMII_IPG_12;
+ break;
+ case IPG1_13_BYTES:
+ attrp->odata[1] = MII_GMII_IPG_13;
+ break;
+ case IPG1_14_BYTES:
+ attrp->odata[1] = MII_GMII_IPG_14;
+ break;
+ case IPG1_15_BYTES:
+ attrp->odata[1] = MII_GMII_IPG_15;
+ break;
+ case IPG1_16_BYTES:
+ attrp->odata[1] = MII_GMII_IPG_16;
+ break;
+ default:
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_IPG:"
+ " Invalid Input: portn <%d>",
+ portn));
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ break;
+ }
+
+ case MAC_PORT_ADDR: {
+ uint32_t addr0;
+ uint32_t addr1;
+ uint32_t addr2;
+
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ addr0 = attrp->idata[0];
+ addr1 = attrp->idata[1];
+ addr2 = attrp->idata[2];
+ if ((addr0 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr0 <0x%x>", addr0));
+
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr1 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr1 <0x%x>", addr1));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr2 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr2 <0x%x.",
+ addr2));
+
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XMAC_ADDR0_REG,
+ addr0);
+ XMAC_REG_WR(handle, portn, XMAC_ADDR1_REG,
+ addr1);
+ XMAC_REG_WR(handle, portn, XMAC_ADDR2_REG,
+ addr2);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_ADDR0_REG,
+ &addr0);
+ XMAC_REG_RD(handle, portn, XMAC_ADDR1_REG,
+ &addr1);
+ XMAC_REG_RD(handle, portn, XMAC_ADDR2_REG,
+ &addr2);
+ attrp->odata[0] = addr0 & MAC_ADDR_REG_MASK;
+ attrp->odata[1] = addr1 & MAC_ADDR_REG_MASK;
+ attrp->odata[2] = addr2 & MAC_ADDR_REG_MASK;
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ addr0 = attrp->idata[0];
+ addr1 = attrp->idata[1];
+ addr2 = attrp->idata[2];
+ if ((addr0 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr0 <0x%x>",
+ addr0));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr1 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr1 <0x%x>",
+ addr1));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr2 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR:"
+ " Invalid Input:"
+ " addr2 <0x%x>",
+ addr2));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, BMAC_ADDR0_REG,
+ addr0);
+ BMAC_REG_WR(handle, portn, BMAC_ADDR1_REG,
+ addr1);
+ BMAC_REG_WR(handle, portn, BMAC_ADDR2_REG,
+ addr2);
+ } else {
+ BMAC_REG_RD(handle, portn, BMAC_ADDR0_REG,
+ &addr0);
+ BMAC_REG_RD(handle, portn, BMAC_ADDR1_REG,
+ &addr1);
+ BMAC_REG_RD(handle, portn, BMAC_ADDR2_REG,
+ &addr2);
+ attrp->odata[0] = addr0 & MAC_ADDR_REG_MASK;
+ attrp->odata[1] = addr1 & MAC_ADDR_REG_MASK;
+ attrp->odata[2] = addr2 & MAC_ADDR_REG_MASK;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case MAC_PORT_ADDR_FILTER: {
+ uint32_t addr0;
+ uint32_t addr1;
+ uint32_t addr2;
+
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ addr0 = attrp->idata[0];
+ addr1 = attrp->idata[1];
+ addr2 = attrp->idata[2];
+ if ((addr0 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " Invalid Input:"
+ " addr0 <0x%x>",
+ addr0));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr1 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " Invalid Input:"
+ " addr1 <0x%x>",
+ addr1));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr2 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " Invalid Input:"
+ " addr2 <0x%x>",
+ addr2));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn,
+ XMAC_ADDR_FILT0_REG, addr0);
+ XMAC_REG_WR(handle, portn,
+ XMAC_ADDR_FILT1_REG, addr1);
+ XMAC_REG_WR(handle, portn,
+ XMAC_ADDR_FILT2_REG, addr2);
+ } else {
+ XMAC_REG_RD(handle, portn,
+ XMAC_ADDR_FILT0_REG, &addr0);
+ XMAC_REG_RD(handle, portn,
+ XMAC_ADDR_FILT1_REG, &addr1);
+ XMAC_REG_RD(handle, portn,
+ XMAC_ADDR_FILT2_REG, &addr2);
+ attrp->odata[0] = addr0 & MAC_ADDR_REG_MASK;
+ attrp->odata[1] = addr1 & MAC_ADDR_REG_MASK;
+ attrp->odata[2] = addr2 & MAC_ADDR_REG_MASK;
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ addr0 = attrp->idata[0];
+ addr1 = attrp->idata[1];
+ addr2 = attrp->idata[2];
+ if ((addr0 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " addr0",
+ addr0));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr1 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " Invalid Input:"
+ " addr1 <0x%x>",
+ addr1));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((addr2 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_PORT_ADDR_FILTER:"
+ " Invalid Input:"
+ " addr2 <0x%x>",
+ addr2));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, MAC_ADDR_FILT0_REG,
+ addr0);
+ BMAC_REG_WR(handle, portn, MAC_ADDR_FILT1_REG,
+ addr1);
+ BMAC_REG_WR(handle, portn, MAC_ADDR_FILT2_REG,
+ addr2);
+ } else {
+ BMAC_REG_RD(handle, portn, MAC_ADDR_FILT0_REG,
+ &addr0);
+ BMAC_REG_RD(handle, portn, MAC_ADDR_FILT1_REG,
+ &addr1);
+ BMAC_REG_RD(handle, portn, MAC_ADDR_FILT2_REG,
+ &addr2);
+ attrp->odata[0] = addr0 & MAC_ADDR_REG_MASK;
+ attrp->odata[1] = addr1 & MAC_ADDR_REG_MASK;
+ attrp->odata[2] = addr2 & MAC_ADDR_REG_MASK;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ case MAC_PORT_ADDR_FILTER_MASK: {
+ uint32_t mask_1_2;
+ uint32_t mask_0;
+
+ switch (portn) {
+ case XMAC_PORT_0:
+ case XMAC_PORT_1:
+ if (op == OP_SET) {
+ mask_0 = attrp->idata[0];
+ mask_1_2 = attrp->idata[1];
+ if ((mask_0 & ~0xFFFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_ADDR_FILTER_MASK:"
+ " Invalid Input:"
+ " mask_0 <0x%x>",
+ mask_0));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ if ((mask_1_2 & ~0xFF) != 0) {
+ NPI_ERROR_MSG((handle.function,
+ NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " MAC_ADDR_FILTER_MASK:"
+ " Invalid Input:"
+ " mask_1_2 <0x%x>",
+ mask_1_2));
+ return (NPI_FAILURE |
+ NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn,
+ XMAC_ADDR_FILT0_MASK_REG, mask_0);
+ XMAC_REG_WR(handle, portn,
+ XMAC_ADDR_FILT12_MASK_REG, mask_1_2);
+ } else {
+ XMAC_REG_RD(handle, portn,
+ XMAC_ADDR_FILT0_MASK_REG, &mask_0);
+ XMAC_REG_RD(handle, portn,
+ XMAC_ADDR_FILT12_MASK_REG, &mask_1_2);
+ attrp->odata[0] = mask_0 & 0xFFFF;
+ attrp->odata[1] = mask_1_2 & 0xFF;
+ }
+ break;
+ case BMAC_PORT_0:
+ case BMAC_PORT_1:
+ if (op == OP_SET) {
+ mask_0 = attrp->idata[0];
+ mask_1_2 = attrp->idata[1];
+ BMAC_REG_WR(handle, portn,
+ MAC_ADDR_FILT00_MASK_REG, mask_0);
+ BMAC_REG_WR(handle, portn,
+ MAC_ADDR_FILT12_MASK_REG, mask_1_2);
+ } else {
+ BMAC_REG_RD(handle, portn,
+ MAC_ADDR_FILT00_MASK_REG, &mask_0);
+ BMAC_REG_RD(handle, portn,
+ MAC_ADDR_FILT12_MASK_REG, &mask_1_2);
+ attrp->odata[0] = mask_0;
+ attrp->odata[1] = mask_1_2;
+ }
+ break;
+ default:
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+ } break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_port_attr"
+ " Invalid Input:"
+ " attr <0x%x>", attrp->type));
+ return (NPI_FAILURE | NPI_MAC_PORT_ATTR_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_reset(npi_handle_t handle, uint8_t portn, npi_mac_reset_t mode)
+{
+ uint64_t val;
+ boolean_t txmac = B_FALSE;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_reset"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (mode) {
+ case XTX_MAC_REG_RESET:
+ XMAC_REG_WR(handle, portn, XTXMAC_SW_RST_REG, XTXMAC_REG_RST);
+ XMAC_WAIT_REG(handle, portn, XTXMAC_SW_RST_REG, val);
+ txmac = B_TRUE;
+ break;
+ case XRX_MAC_REG_RESET:
+ XMAC_REG_WR(handle, portn, XRXMAC_SW_RST_REG, XRXMAC_REG_RST);
+ XMAC_WAIT_REG(handle, portn, XRXMAC_SW_RST_REG, val);
+ break;
+ case XTX_MAC_LOGIC_RESET:
+ XMAC_REG_WR(handle, portn, XTXMAC_SW_RST_REG, XTXMAC_SOFT_RST);
+ XMAC_WAIT_REG(handle, portn, XTXMAC_SW_RST_REG, val);
+ txmac = B_TRUE;
+ break;
+ case XRX_MAC_LOGIC_RESET:
+ XMAC_REG_WR(handle, portn, XRXMAC_SW_RST_REG, XRXMAC_SOFT_RST);
+ XMAC_WAIT_REG(handle, portn, XRXMAC_SW_RST_REG, val);
+ break;
+ case XTX_MAC_RESET_ALL:
+ XMAC_REG_WR(handle, portn, XTXMAC_SW_RST_REG,
+ XTXMAC_SOFT_RST | XTXMAC_REG_RST);
+ XMAC_WAIT_REG(handle, portn, XTXMAC_SW_RST_REG, val);
+ txmac = B_TRUE;
+ break;
+ case XRX_MAC_RESET_ALL:
+ XMAC_REG_WR(handle, portn, XRXMAC_SW_RST_REG,
+ XRXMAC_SOFT_RST | XRXMAC_REG_RST);
+ XMAC_WAIT_REG(handle, portn, XRXMAC_SW_RST_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_reset"
+ " Invalid Input: mode <0x%x>",
+ mode));
+ return (NPI_FAILURE | NPI_MAC_RESET_MODE_INVALID(portn));
+ }
+
+ if (val != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_reset"
+ " HW ERROR: MAC_RESET failed <0x%x>",
+ val));
+
+ if (txmac == B_TRUE)
+ return (NPI_FAILURE | NPI_TXMAC_RESET_FAILED(portn));
+ else
+ return (NPI_FAILURE | NPI_RXMAC_RESET_FAILED(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xif_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_xif_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xif_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_XMAC_XIF_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xif_config"
+ " Invalid Input:"
+ " config <0x%x>", config));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_XIF_LED_FORCE)
+ val |= XMAC_XIF_FORCE_LED_ON;
+ if (config & CFG_XMAC_XIF_LED_POLARITY)
+ val |= XMAC_XIF_LED_POLARITY;
+ if (config & CFG_XMAC_XIF_SEL_POR_CLK_SRC)
+ val |= XMAC_XIF_SEL_POR_CLK_SRC;
+ if (config & CFG_XMAC_XIF_TX_OUTPUT)
+ val |= XMAC_XIF_TX_OUTPUT_EN;
+
+ if (config & CFG_XMAC_XIF_LOOPBACK) {
+ val &= ~XMAC_XIF_SEL_POR_CLK_SRC;
+ val |= XMAC_XIF_LOOPBACK;
+ }
+
+ if (config & CFG_XMAC_XIF_LFS)
+ val &= ~XMAC_XIF_LFS_DISABLE;
+ if (config & CFG_XMAC_XIF_XPCS_BYPASS)
+ val |= XMAC_XIF_XPCS_BYPASS;
+ if (config & CFG_XMAC_XIF_1G_PCS_BYPASS)
+ val |= XMAC_XIF_1G_PCS_BYPASS;
+ if (config & CFG_XMAC_XIF_SEL_CLK_25MHZ)
+ val |= XMAC_XIF_SEL_CLK_25MHZ;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_XIF_LED_FORCE)
+ val &= ~XMAC_XIF_FORCE_LED_ON;
+ if (config & CFG_XMAC_XIF_LED_POLARITY)
+ val &= ~XMAC_XIF_LED_POLARITY;
+ if (config & CFG_XMAC_XIF_SEL_POR_CLK_SRC)
+ val &= ~XMAC_XIF_SEL_POR_CLK_SRC;
+ if (config & CFG_XMAC_XIF_TX_OUTPUT)
+ val &= ~XMAC_XIF_TX_OUTPUT_EN;
+ if (config & CFG_XMAC_XIF_LOOPBACK)
+ val &= ~XMAC_XIF_LOOPBACK;
+ if (config & CFG_XMAC_XIF_LFS)
+ val |= XMAC_XIF_LFS_DISABLE;
+ if (config & CFG_XMAC_XIF_XPCS_BYPASS)
+ val &= ~XMAC_XIF_XPCS_BYPASS;
+ if (config & CFG_XMAC_XIF_1G_PCS_BYPASS)
+ val &= ~XMAC_XIF_1G_PCS_BYPASS;
+ if (config & CFG_XMAC_XIF_SEL_CLK_25MHZ)
+ val &= ~XMAC_XIF_SEL_CLK_25MHZ;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_XMAC_XIF_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xif_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+
+ if (config & CFG_XMAC_XIF_LED_FORCE)
+ val |= XMAC_XIF_FORCE_LED_ON;
+ else
+ val &= ~XMAC_XIF_FORCE_LED_ON;
+ if (config & CFG_XMAC_XIF_LED_POLARITY)
+ val |= XMAC_XIF_LED_POLARITY;
+ else
+ val &= ~XMAC_XIF_LED_POLARITY;
+ if (config & CFG_XMAC_XIF_SEL_POR_CLK_SRC)
+ val |= XMAC_XIF_SEL_POR_CLK_SRC;
+ else
+ val &= ~XMAC_XIF_SEL_POR_CLK_SRC;
+ if (config & CFG_XMAC_XIF_TX_OUTPUT)
+ val |= XMAC_XIF_TX_OUTPUT_EN;
+ else
+ val &= ~XMAC_XIF_TX_OUTPUT_EN;
+
+ if (config & CFG_XMAC_XIF_LOOPBACK) {
+ val &= ~XMAC_XIF_SEL_POR_CLK_SRC;
+ val |= XMAC_XIF_LOOPBACK;
+#ifdef AXIS_DEBUG_LB
+ val |= XMAC_RX_MAC2IPP_PKT_CNT_EN;
+#endif
+ } else {
+ val &= ~XMAC_XIF_LOOPBACK;
+ }
+
+ if (config & CFG_XMAC_XIF_LFS)
+ val &= ~XMAC_XIF_LFS_DISABLE;
+ else
+ val |= XMAC_XIF_LFS_DISABLE;
+ if (config & CFG_XMAC_XIF_XPCS_BYPASS)
+ val |= XMAC_XIF_XPCS_BYPASS;
+ else
+ val &= ~XMAC_XIF_XPCS_BYPASS;
+ if (config & CFG_XMAC_XIF_1G_PCS_BYPASS)
+ val |= XMAC_XIF_1G_PCS_BYPASS;
+ else
+ val &= ~XMAC_XIF_1G_PCS_BYPASS;
+ if (config & CFG_XMAC_XIF_SEL_CLK_25MHZ)
+ val |= XMAC_XIF_SEL_CLK_25MHZ;
+ else
+ val &= ~XMAC_XIF_SEL_CLK_25MHZ;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xif_config"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_tx_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_tx_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_TX)
+ val |= XMAC_TX_CFG_TX_ENABLE;
+ if (config & CFG_XMAC_TX_STRETCH_MODE)
+ val |= XMAC_TX_CFG_STRETCH_MD;
+ if (config & CFG_XMAC_VAR_IPG)
+ val |= XMAC_TX_CFG_VAR_MIN_IPG_EN;
+ if (config & CFG_XMAC_TX_CRC)
+ val &= ~XMAC_TX_CFG_ALWAYS_NO_CRC;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_TX)
+ val &= ~XMAC_TX_CFG_TX_ENABLE;
+ if (config & CFG_XMAC_TX_STRETCH_MODE)
+ val &= ~XMAC_TX_CFG_STRETCH_MD;
+ if (config & CFG_XMAC_VAR_IPG)
+ val &= ~XMAC_TX_CFG_VAR_MIN_IPG_EN;
+ if (config & CFG_XMAC_TX_CRC)
+ val |= XMAC_TX_CFG_ALWAYS_NO_CRC;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_TX)
+ val |= XMAC_TX_CFG_TX_ENABLE;
+ else
+ val &= ~XMAC_TX_CFG_TX_ENABLE;
+ if (config & CFG_XMAC_TX_STRETCH_MODE)
+ val |= XMAC_TX_CFG_STRETCH_MD;
+ else
+ val &= ~XMAC_TX_CFG_STRETCH_MD;
+ if (config & CFG_XMAC_VAR_IPG)
+ val |= XMAC_TX_CFG_VAR_MIN_IPG_EN;
+ else
+ val &= ~XMAC_TX_CFG_VAR_MIN_IPG_EN;
+ if (config & CFG_XMAC_TX_CRC)
+ val &= ~XMAC_TX_CFG_ALWAYS_NO_CRC;
+ else
+ val |= XMAC_TX_CFG_ALWAYS_NO_CRC;
+
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_config"
+ " Invalid Input: op <0x%x>",
+ op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_rx_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_rx_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_XMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_RX)
+ val |= XMAC_RX_CFG_RX_ENABLE;
+ if (config & CFG_XMAC_RX_PROMISCUOUS)
+ val |= XMAC_RX_CFG_PROMISC;
+ if (config & CFG_XMAC_RX_PROMISCUOUSGROUP)
+ val |= XMAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_XMAC_RX_ERRCHK)
+ val &= ~XMAC_RX_CFG_ERR_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_CRC_CHK)
+ val &= ~XMAC_RX_CFG_CRC_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_RESV_MULTICAST)
+ val |= XMAC_RX_CFG_RESERVED_MCAST;
+ if (config & CFG_XMAC_RX_CODE_VIO_CHK)
+ val &= ~XMAC_RX_CFG_CD_VIO_CHK;
+ if (config & CFG_XMAC_RX_HASH_FILTER)
+ val |= XMAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_XMAC_RX_ADDR_FILTER)
+ val |= XMAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_XMAC_RX_STRIP_CRC)
+ val |= XMAC_RX_CFG_STRIP_CRC;
+ if (config & CFG_XMAC_RX_PAUSE)
+ val |= XMAC_RX_CFG_RX_PAUSE_EN;
+ if (config & CFG_XMAC_RX_PASS_FC_FRAME)
+ val |= XMAC_RX_CFG_PASS_FLOW_CTRL;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ } else {
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_RX)
+ val &= ~XMAC_RX_CFG_RX_ENABLE;
+ if (config & CFG_XMAC_RX_PROMISCUOUS)
+ val &= ~XMAC_RX_CFG_PROMISC;
+ if (config & CFG_XMAC_RX_PROMISCUOUSGROUP)
+ val &= ~XMAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_XMAC_RX_ERRCHK)
+ val |= XMAC_RX_CFG_ERR_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_CRC_CHK)
+ val |= XMAC_RX_CFG_CRC_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_RESV_MULTICAST)
+ val &= ~XMAC_RX_CFG_RESERVED_MCAST;
+ if (config & CFG_XMAC_RX_CODE_VIO_CHK)
+ val |= XMAC_RX_CFG_CD_VIO_CHK;
+ if (config & CFG_XMAC_RX_HASH_FILTER)
+ val &= ~XMAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_XMAC_RX_ADDR_FILTER)
+ val &= ~XMAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_XMAC_RX_STRIP_CRC)
+ val &= ~XMAC_RX_CFG_STRIP_CRC;
+ if (config & CFG_XMAC_RX_PAUSE)
+ val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
+ if (config & CFG_XMAC_RX_PASS_FC_FRAME)
+ val &= ~XMAC_RX_CFG_PASS_FLOW_CTRL;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_XMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ if (config & CFG_XMAC_RX)
+ val |= XMAC_RX_CFG_RX_ENABLE;
+ else
+ val &= ~XMAC_RX_CFG_RX_ENABLE;
+ if (config & CFG_XMAC_RX_PROMISCUOUS)
+ val |= XMAC_RX_CFG_PROMISC;
+ else
+ val &= ~XMAC_RX_CFG_PROMISC;
+ if (config & CFG_XMAC_RX_PROMISCUOUSGROUP)
+ val |= XMAC_RX_CFG_PROMISC_GROUP;
+ else
+ val &= ~XMAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_XMAC_RX_ERRCHK)
+ val &= ~XMAC_RX_CFG_ERR_CHK_DISABLE;
+ else
+ val |= XMAC_RX_CFG_ERR_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_CRC_CHK)
+ val &= ~XMAC_RX_CFG_CRC_CHK_DISABLE;
+ else
+ val |= XMAC_RX_CFG_CRC_CHK_DISABLE;
+ if (config & CFG_XMAC_RX_RESV_MULTICAST)
+ val |= XMAC_RX_CFG_RESERVED_MCAST;
+ else
+ val &= ~XMAC_RX_CFG_RESERVED_MCAST;
+ if (config & CFG_XMAC_RX_CODE_VIO_CHK)
+ val &= ~XMAC_RX_CFG_CD_VIO_CHK;
+ else
+ val |= XMAC_RX_CFG_CD_VIO_CHK;
+ if (config & CFG_XMAC_RX_HASH_FILTER)
+ val |= XMAC_RX_CFG_HASH_FILTER_EN;
+ else
+ val &= ~XMAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_XMAC_RX_ADDR_FILTER)
+ val |= XMAC_RX_CFG_ADDR_FILTER_EN;
+ else
+ val &= ~XMAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_XMAC_RX_PAUSE)
+ val |= XMAC_RX_CFG_RX_PAUSE_EN;
+ else
+ val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
+ if (config & CFG_XMAC_RX_STRIP_CRC)
+ val |= XMAC_RX_CFG_STRIP_CRC;
+ else
+ val &= ~XMAC_RX_CFG_STRIP_CRC;
+ if (config & CFG_XMAC_RX_PASS_FC_FRAME)
+ val |= XMAC_RX_CFG_PASS_FLOW_CTRL;
+ else
+ val &= ~XMAC_RX_CFG_PASS_FLOW_CTRL;
+
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_config"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_tx_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_tx_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XTXMAC_STAT_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ XMAC_REG_WR(handle, portn, XTXMAC_STAT_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XTXMAC_STAT_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_rx_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_rx_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_XMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XRXMAC_STAT_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ XMAC_REG_WR(handle, portn, XRXMAC_STAT_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_XMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XRXMAC_STAT_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_ctl_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ xmac_ctl_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_ctl_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_XMAC_CTRL_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_RD(handle, portn, XMAC_C_S_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ XMAC_REG_WR(handle, portn, XMAC_C_S_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_XMAC_CTRL_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ XMAC_REG_WR(handle, portn, XMAC_C_S_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_tx_get_istatus(npi_handle_t handle, uint8_t portn,
+ xmac_tx_iconfig_t *istatus)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_tx_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XTXMAC_STATUS_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_rx_get_istatus(npi_handle_t handle, uint8_t portn,
+ xmac_rx_iconfig_t *istatus)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_rx_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XRXMAC_STATUS_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_ctl_get_istatus(npi_handle_t handle, uint8_t portn,
+ xmac_ctl_iconfig_t *istatus)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_ctl_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XMAC_CTRL_STAT_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_reset(npi_handle_t handle, uint8_t portn)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_reset"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XPCS_REG_RD(handle, portn, XPCS_CTRL_1_REG, &val);
+ val |= XPCS_CTRL1_RST;
+ XPCS_REG_WR(handle, portn, XPCS_CTRL_1_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_enable(npi_handle_t handle, uint8_t portn)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_enable"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XPCS_REG_RD(handle, portn, XPCS_CFG_VENDOR_1_REG, &val);
+ val |= XPCS_CFG_XPCS_ENABLE;
+ XPCS_REG_WR(handle, portn, XPCS_CFG_VENDOR_1_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_disable(npi_handle_t handle, uint8_t portn)
+{
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_disable"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XPCS_REG_RD(handle, portn, XPCS_CFG_VENDOR_1_REG, &val);
+ val &= ~XPCS_CFG_XPCS_ENABLE;
+ XPCS_REG_WR(handle, portn, XPCS_CFG_VENDOR_1_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_read(npi_handle_t handle, uint8_t portn, uint8_t xpcs_reg,
+ uint32_t *value)
+{
+ uint32_t reg;
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_read"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (xpcs_reg) {
+ case XPCS_REG_CONTROL1:
+ reg = XPCS_CTRL_1_REG;
+ break;
+ case XPCS_REG_STATUS1:
+ reg = XPCS_STATUS_1_REG;
+ break;
+ case XPCS_REG_DEVICE_ID:
+ reg = XPCS_DEV_ID_REG;
+ break;
+ case XPCS_REG_SPEED_ABILITY:
+ reg = XPCS_SPEED_ABILITY_REG;
+ break;
+ case XPCS_REG_DEVICE_IN_PKG:
+ reg = XPCS_DEV_IN_PKG_REG;
+ break;
+ case XPCS_REG_CONTROL2:
+ reg = XPCS_CTRL_2_REG;
+ break;
+ case XPCS_REG_STATUS2:
+ reg = XPCS_STATUS_2_REG;
+ break;
+ case XPCS_REG_PKG_ID:
+ reg = XPCS_PKG_ID_REG;
+ break;
+ case XPCS_REG_STATUS:
+ reg = XPCS_STATUS_REG;
+ break;
+ case XPCS_REG_TEST_CONTROL:
+ reg = XPCS_TEST_CTRL_REG;
+ break;
+ case XPCS_REG_CONFIG_VENDOR1:
+ reg = XPCS_CFG_VENDOR_1_REG;
+ break;
+ case XPCS_REG_DIAG_VENDOR2:
+ reg = XPCS_DIAG_VENDOR_2_REG;
+ break;
+ case XPCS_REG_MASK1:
+ reg = XPCS_MASK_1_REG;
+ break;
+ case XPCS_REG_PACKET_COUNTER:
+ reg = XPCS_PKT_CNTR_REG;
+ break;
+ case XPCS_REG_TX_STATEMACHINE:
+ reg = XPCS_TX_STATE_MC_REG;
+ break;
+ case XPCS_REG_DESCWERR_COUNTER:
+ reg = XPCS_DESKEW_ERR_CNTR_REG;
+ break;
+ case XPCS_REG_SYMBOL_ERR_L0_1_COUNTER:
+ reg = XPCS_SYM_ERR_CNTR_L0_L1_REG;
+ break;
+ case XPCS_REG_SYMBOL_ERR_L2_3_COUNTER:
+ reg = XPCS_SYM_ERR_CNTR_L2_L3_REG;
+ break;
+ case XPCS_REG_TRAINING_VECTOR:
+ reg = XPCS_TRAINING_VECTOR_REG;
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_read"
+ " Invalid Input: xpcs_reg <0x%x>",
+ xpcs_reg));
+ return (NPI_FAILURE | NPI_MAC_REG_INVALID(portn));
+ }
+ XPCS_REG_RD(handle, portn, reg, &val);
+ *value = val & 0xFFFFFFFF;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xpcs_write(npi_handle_t handle, uint8_t portn, uint8_t xpcs_reg,
+ uint32_t value)
+{
+ uint32_t reg;
+ uint64_t val;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_write"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (xpcs_reg) {
+ case XPCS_REG_CONTROL1:
+ reg = XPCS_CTRL_1_REG;
+ break;
+ case XPCS_REG_TEST_CONTROL:
+ reg = XPCS_TEST_CTRL_REG;
+ break;
+ case XPCS_REG_CONFIG_VENDOR1:
+ reg = XPCS_CFG_VENDOR_1_REG;
+ break;
+ case XPCS_REG_DIAG_VENDOR2:
+ reg = XPCS_DIAG_VENDOR_2_REG;
+ break;
+ case XPCS_REG_MASK1:
+ reg = XPCS_MASK_1_REG;
+ break;
+ case XPCS_REG_PACKET_COUNTER:
+ reg = XPCS_PKT_CNTR_REG;
+ break;
+ case XPCS_REG_DESCWERR_COUNTER:
+ reg = XPCS_DESKEW_ERR_CNTR_REG;
+ break;
+ case XPCS_REG_TRAINING_VECTOR:
+ reg = XPCS_TRAINING_VECTOR_REG;
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_xpcs_write"
+ " Invalid Input: xpcs_reg <0x%x>",
+ xpcs_reg));
+ return (NPI_FAILURE | NPI_MAC_PCS_REG_INVALID(portn));
+ }
+ val = value;
+
+ XPCS_REG_WR(handle, portn, reg, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_reset(npi_handle_t handle, uint8_t portn, npi_mac_reset_t mode)
+{
+ uint64_t val = 0;
+ boolean_t txmac = B_FALSE;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_reset"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (mode) {
+ case TX_MAC_RESET:
+ BMAC_REG_WR(handle, portn, BTXMAC_SW_RST_REG, 0x1);
+ BMAC_WAIT_REG(handle, portn, BTXMAC_SW_RST_REG, val);
+ txmac = B_TRUE;
+ break;
+ case RX_MAC_RESET:
+ BMAC_REG_WR(handle, portn, BRXMAC_SW_RST_REG, 0x1);
+ BMAC_WAIT_REG(handle, portn, BRXMAC_SW_RST_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_reset"
+ " Invalid Input: mode <0x%x>",
+ mode));
+ return (NPI_FAILURE | NPI_MAC_RESET_MODE_INVALID(portn));
+ }
+
+ if (val != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_reset"
+ " BMAC_RESET HW Error: ret <0x%x>",
+ val));
+ if (txmac == B_TRUE)
+ return (NPI_FAILURE | NPI_TXMAC_RESET_FAILED(portn));
+ else
+ return (NPI_FAILURE | NPI_RXMAC_RESET_FAILED(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_pcs_reset(npi_handle_t handle, uint8_t portn)
+{
+ /* what to do here ? */
+ uint64_t val = 0;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_pcs_reset"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ PCS_REG_RD(handle, portn, PCS_MII_CTRL_REG, &val);
+ val |= PCS_MII_RESET;
+ PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_get_link_status(npi_handle_t handle, uint8_t portn,
+ boolean_t *link_up)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_get_link_status"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ PCS_REG_RD(handle, portn, PCS_MII_STATUS_REG, &val);
+
+ if (val & PCS_MII_STATUS_LINK_STATUS) {
+ *link_up = B_TRUE;
+ } else {
+ *link_up = B_FALSE;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_tx_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_tx_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_BMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ BMAC_REG_RD(handle, portn, TXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_TX)
+ val |= MAC_TX_CFG_TXMAC_ENABLE;
+ if (config & CFG_BMAC_TX_CRC)
+ val &= ~MAC_TX_CFG_NO_FCS;
+ BMAC_REG_WR(handle, portn, TXMAC_CONFIG_REG, val);
+ } else {
+ BMAC_REG_RD(handle, portn, TXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_TX)
+ val &= ~MAC_TX_CFG_TXMAC_ENABLE;
+ if (config & CFG_BMAC_TX_CRC)
+ val |= MAC_TX_CFG_NO_FCS;
+ BMAC_REG_WR(handle, portn, TXMAC_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_BMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, TXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_TX)
+ val |= MAC_TX_CFG_TXMAC_ENABLE;
+ else
+ val &= ~MAC_TX_CFG_TXMAC_ENABLE;
+ if (config & CFG_BMAC_TX_CRC)
+ val &= ~MAC_TX_CFG_NO_FCS;
+ else
+ val |= MAC_TX_CFG_NO_FCS;
+ BMAC_REG_WR(handle, portn, TXMAC_CONFIG_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_config"
+ " Invalid Input: op <0x%x>",
+ op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_rx_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_rx_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_BMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ BMAC_REG_RD(handle, portn, RXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_RX)
+ val |= MAC_RX_CFG_RXMAC_ENABLE;
+ if (config & CFG_BMAC_RX_STRIP_PAD)
+ val |= MAC_RX_CFG_STRIP_PAD;
+ if (config & CFG_BMAC_RX_STRIP_CRC)
+ val |= MAC_RX_CFG_STRIP_FCS;
+ if (config & CFG_BMAC_RX_PROMISCUOUS)
+ val |= MAC_RX_CFG_PROMISC;
+ if (config & CFG_BMAC_RX_PROMISCUOUSGROUP)
+ val |= MAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_BMAC_RX_HASH_FILTER)
+ val |= MAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_BMAC_RX_ADDR_FILTER)
+ val |= MAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_BMAC_RX_DISCARD_ON_ERR)
+ val &= ~MAC_RX_CFG_DISABLE_DISCARD;
+ BMAC_REG_WR(handle, portn, RXMAC_CONFIG_REG, val);
+ } else {
+ BMAC_REG_RD(handle, portn, RXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_RX)
+ val &= ~MAC_RX_CFG_RXMAC_ENABLE;
+ if (config & CFG_BMAC_RX_STRIP_PAD)
+ val &= ~MAC_RX_CFG_STRIP_PAD;
+ if (config & CFG_BMAC_RX_STRIP_CRC)
+ val &= ~MAC_RX_CFG_STRIP_FCS;
+ if (config & CFG_BMAC_RX_PROMISCUOUS)
+ val &= ~MAC_RX_CFG_PROMISC;
+ if (config & CFG_BMAC_RX_PROMISCUOUSGROUP)
+ val &= ~MAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_BMAC_RX_HASH_FILTER)
+ val &= ~MAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_BMAC_RX_ADDR_FILTER)
+ val &= ~MAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_BMAC_RX_DISCARD_ON_ERR)
+ val |= MAC_RX_CFG_DISABLE_DISCARD;
+ BMAC_REG_WR(handle, portn, RXMAC_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_BMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, RXMAC_CONFIG_REG, &val);
+ if (config & CFG_BMAC_RX)
+ val |= MAC_RX_CFG_RXMAC_ENABLE;
+ else
+ val &= ~MAC_RX_CFG_RXMAC_ENABLE;
+ if (config & CFG_BMAC_RX_STRIP_PAD)
+ val |= MAC_RX_CFG_STRIP_PAD;
+ else
+ val &= ~MAC_RX_CFG_STRIP_PAD;
+ if (config & CFG_BMAC_RX_STRIP_CRC)
+ val |= MAC_RX_CFG_STRIP_FCS;
+ else
+ val &= ~MAC_RX_CFG_STRIP_FCS;
+ if (config & CFG_BMAC_RX_PROMISCUOUS)
+ val |= MAC_RX_CFG_PROMISC;
+ else
+ val &= ~MAC_RX_CFG_PROMISC;
+ if (config & CFG_BMAC_RX_PROMISCUOUSGROUP)
+ val |= MAC_RX_CFG_PROMISC_GROUP;
+ else
+ val &= ~MAC_RX_CFG_PROMISC_GROUP;
+ if (config & CFG_BMAC_RX_HASH_FILTER)
+ val |= MAC_RX_CFG_HASH_FILTER_EN;
+ else
+ val &= ~MAC_RX_CFG_HASH_FILTER_EN;
+ if (config & CFG_BMAC_RX_ADDR_FILTER)
+ val |= MAC_RX_CFG_ADDR_FILTER_EN;
+ else
+ val &= ~MAC_RX_CFG_ADDR_FILTER_EN;
+ if (config & CFG_BMAC_RX_DISCARD_ON_ERR)
+ val &= ~MAC_RX_CFG_DISABLE_DISCARD;
+ else
+ val |= MAC_RX_CFG_DISABLE_DISCARD;
+
+ BMAC_REG_WR(handle, portn, RXMAC_CONFIG_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_config"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_rx_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_rx_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_BMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BRXMAC_STAT_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ BMAC_REG_WR(handle, portn, BRXMAC_STAT_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_BMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, BRXMAC_STAT_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_xif_config(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_xif_config_t config)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_xif_config"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_BMAC_XIF_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_xif_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ if (op == ENABLE) {
+ BMAC_REG_RD(handle, portn, MAC_XIF_CONFIG_REG, &val);
+ if (config & CFG_BMAC_XIF_TX_OUTPUT)
+ val |= MAC_XIF_TX_OUTPUT_EN;
+ if (config & CFG_BMAC_XIF_LOOPBACK)
+ val |= MAC_XIF_MII_INT_LOOPBACK;
+ if (config & CFG_BMAC_XIF_GMII_MODE)
+ val |= MAC_XIF_GMII_MODE;
+ if (config & CFG_BMAC_XIF_LINKLED)
+ val |= MAC_XIF_LINK_LED;
+ if (config & CFG_BMAC_XIF_LED_POLARITY)
+ val |= MAC_XIF_LED_POLARITY;
+ if (config & CFG_BMAC_XIF_SEL_CLK_25MHZ)
+ val |= MAC_XIF_SEL_CLK_25MHZ;
+ BMAC_REG_WR(handle, portn, MAC_XIF_CONFIG_REG, val);
+ } else {
+ BMAC_REG_RD(handle, portn, MAC_XIF_CONFIG_REG, &val);
+ if (config & CFG_BMAC_XIF_TX_OUTPUT)
+ val &= ~MAC_XIF_TX_OUTPUT_EN;
+ if (config & CFG_BMAC_XIF_LOOPBACK)
+ val &= ~MAC_XIF_MII_INT_LOOPBACK;
+ if (config & CFG_BMAC_XIF_GMII_MODE)
+ val &= ~MAC_XIF_GMII_MODE;
+ if (config & CFG_BMAC_XIF_LINKLED)
+ val &= ~MAC_XIF_LINK_LED;
+ if (config & CFG_BMAC_XIF_LED_POLARITY)
+ val &= ~MAC_XIF_LED_POLARITY;
+ if (config & CFG_BMAC_XIF_SEL_CLK_25MHZ)
+ val &= ~MAC_XIF_SEL_CLK_25MHZ;
+ BMAC_REG_WR(handle, portn, MAC_XIF_CONFIG_REG, val);
+ }
+ break;
+ case INIT:
+ if ((config & ~CFG_BMAC_XIF_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_xif_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, MAC_XIF_CONFIG_REG, &val);
+ if (config & CFG_BMAC_XIF_TX_OUTPUT)
+ val |= MAC_XIF_TX_OUTPUT_EN;
+ else
+ val &= ~MAC_XIF_TX_OUTPUT_EN;
+ if (config & CFG_BMAC_XIF_LOOPBACK)
+ val |= MAC_XIF_MII_INT_LOOPBACK;
+ else
+ val &= ~MAC_XIF_MII_INT_LOOPBACK;
+ if (config & CFG_BMAC_XIF_GMII_MODE)
+ val |= MAC_XIF_GMII_MODE;
+ else
+ val &= ~MAC_XIF_GMII_MODE;
+/* if (config & CFG_BMAC_XIF_MII_BUF_OE) */
+/* val |= MAC_XIF_MII_BUFFER_OUTPUT_EN; */
+/* else */
+/* val &= ~MAC_XIF_MII_BUFFER_OUTPUT_EN; */
+ if (config & CFG_BMAC_XIF_LINKLED)
+ val |= MAC_XIF_LINK_LED;
+ else
+ val &= ~MAC_XIF_LINK_LED;
+ if (config & CFG_BMAC_XIF_LED_POLARITY)
+ val |= MAC_XIF_LED_POLARITY;
+ else
+ val &= ~MAC_XIF_LED_POLARITY;
+ if (config & CFG_BMAC_XIF_SEL_CLK_25MHZ)
+ val |= MAC_XIF_SEL_CLK_25MHZ;
+ else
+ val &= ~MAC_XIF_SEL_CLK_25MHZ;
+ BMAC_REG_WR(handle, portn, MAC_XIF_CONFIG_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_xif_config"
+ " Invalid Input: op <0x%x>",
+ op));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_tx_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_tx_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BTXMAC_STAT_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ BMAC_REG_WR(handle, portn, BTXMAC_STAT_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_XMAC_TX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, BTXMAC_STAT_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_ctl_iconfig(npi_handle_t handle, config_op_t op, uint8_t portn,
+ bmac_ctl_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_ctl_iconfig"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+
+ if ((iconfig == 0) || (iconfig & ~ICFG_BMAC_CTL_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_RD(handle, portn, BMAC_C_S_MSK_REG, &val);
+ if (op == ENABLE)
+ val &= ~iconfig;
+ else
+ val |= iconfig;
+ BMAC_REG_WR(handle, portn, BMAC_C_S_MSK_REG, val);
+
+ break;
+ case INIT:
+
+ if ((iconfig & ~ICFG_BMAC_RX_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_CONFIG_INVALID(portn));
+ }
+ BMAC_REG_WR(handle, portn, BMAC_C_S_MSK_REG, ~iconfig);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_ctl_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_MAC_OPCODE_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_tx_get_istatus(npi_handle_t handle, uint8_t portn,
+ bmac_tx_iconfig_t *istatus)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_tx_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ BMAC_REG_RD(handle, portn, BTXMAC_STATUS_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_rx_get_istatus(npi_handle_t handle, uint8_t portn,
+ bmac_rx_iconfig_t *istatus)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_rx_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ BMAC_REG_RD(handle, portn, BRXMAC_STATUS_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_bmac_ctl_get_istatus(npi_handle_t handle, uint8_t portn,
+ bmac_ctl_iconfig_t *istatus)
+{
+ uint64_t val = 0;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_ctl_get_istatus"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ BMAC_REG_RD(handle, portn, BMAC_CTRL_STAT_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_mdio_read(npi_handle_t handle, uint8_t portn, uint8_t device,
+ uint16_t xcvr_reg, uint16_t *value)
+{
+ mif_frame_t frame;
+ uint_t delay;
+
+ frame.value = 0;
+ frame.bits.w0.st = FRAME45_ST; /* Clause 45 */
+ frame.bits.w0.op = FRAME45_OP_ADDR; /* Select address */
+ frame.bits.w0.phyad = portn; /* Port number */
+ frame.bits.w0.regad = device; /* Device number */
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ frame.bits.w0.data = xcvr_reg; /* register address */
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio read port %d addr val=0x%x\n", portn, frame.value));
+
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && (delay < 500));
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio read port %d addr poll=0x%x\n", portn, frame.value));
+
+ if (delay == 500) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "mdio read no response1\n"));
+ /* return (NPI_FAILURE | NPI_MAC_MII_READ_FAILED(portn)); */
+ }
+
+ frame.bits.w0.st = FRAME45_ST; /* Clause 45 */
+ frame.bits.w0.op = FRAME45_OP_READ; /* Read */
+ frame.bits.w0.phyad = portn; /* Port Number */
+ frame.bits.w0.regad = device; /* Device Number */
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio read port %d data frame=0x%x\n", portn, frame.value));
+
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && (delay < 500));
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio read port %d data poll=0x%x\n", portn, frame.value));
+
+ *value = frame.bits.w0.data;
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio read port=%d val=0x%x\n", portn, *value));
+
+ if (delay == 500) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "mdio read no response2\n"));
+ /* return (NPI_FAILURE | NPI_MAC_MII_READ_FAILED(portn)); */
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_mii_read(npi_handle_t handle, uint8_t portn, uint8_t xcvr_reg,
+ uint16_t *value)
+{
+ mif_frame_t frame;
+ uint_t delay;
+
+ frame.bits.w0.st = 0x1; /* Clause 22 */
+ frame.bits.w0.op = 0x2;
+ frame.bits.w0.phyad = portn;
+ frame.bits.w0.regad = xcvr_reg;
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && (delay < MAX_PIO_RETRIES));
+
+ if (delay == MAX_PIO_RETRIES)
+ return (NPI_FAILURE | NPI_MAC_MII_READ_FAILED(portn));
+
+ *value = frame.bits.w0.data;
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mif mii read port %d reg=0x%x frame=0x%x\n", portn,
+ xcvr_reg, frame.bits.w0.data));
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_mdio_write(npi_handle_t handle, uint8_t portn, uint8_t device,
+ uint16_t xcvr_reg, uint16_t value)
+{
+ mif_frame_t frame;
+ uint_t delay;
+
+ frame.value = 0;
+ frame.bits.w0.st = FRAME45_ST; /* Clause 45 */
+ frame.bits.w0.op = FRAME45_OP_ADDR; /* Select Address */
+ frame.bits.w0.phyad = portn; /* Port Number */
+ frame.bits.w0.regad = device; /* Device Number */
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ frame.bits.w0.data = xcvr_reg; /* register address */
+
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio write port %d addr val=0x%x\n", portn, frame.value));
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && delay < 500);
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio write port %d addr poll=0x%x\n", portn, frame.value));
+
+ if (delay == 500) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "mdio write no response1\n"));
+ /* return (NPI_FAILURE | NPI_MAC_MII_READ_FAILED(portn)); */
+ }
+
+ frame.bits.w0.st = FRAME45_ST; /* Clause 45 */
+ frame.bits.w0.op = FRAME45_OP_WRITE; /* Write */
+ frame.bits.w0.phyad = portn; /* Port number */
+ frame.bits.w0.regad = device; /* Device number */
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ frame.bits.w0.data = value;
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio write port %d data val=0x%x\n", portn, frame.value));
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && delay < 500);
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mdio write port %d data poll=0x%x\n", portn, frame.value));
+
+ if (delay == 500) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "mdio write no response2\n"));
+ /* return (NPI_FAILURE | NPI_MAC_MII_READ_FAILED(portn)); */
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_mii_write(npi_handle_t handle, uint8_t portn, uint8_t xcvr_reg,
+ uint16_t value)
+{
+ mif_frame_t frame;
+ uint_t delay;
+
+ frame.bits.w0.st = 0x1; /* Clause 22 */
+ frame.bits.w0.op = 0x1;
+ frame.bits.w0.phyad = portn;
+ frame.bits.w0.regad = xcvr_reg;
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ frame.bits.w0.data = value;
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value);
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && delay < MAX_PIO_RETRIES);
+
+ NPI_DEBUG_MSG((handle.function, MIF_CTL,
+ "mif mii write port %d reg=0x%x frame=0x%x\n", portn,
+ xcvr_reg, frame.value));
+
+ if (delay == MAX_PIO_RETRIES)
+ return (NPI_FAILURE | NPI_MAC_MII_WRITE_FAILED(portn));
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_mac_pcs_mii_read(npi_handle_t handle, uint8_t portn, uint8_t xcvr_reg,
+ uint16_t *value)
+{
+ pcs_anar_t pcs_anar;
+ pcs_anar_t pcs_anlpar;
+ pcs_stat_t pcs_stat;
+ pcs_stat_mc_t pcs_stat_mc;
+ mii_anar_t anar;
+ mii_anar_t anlpar;
+ mii_aner_t aner;
+ mii_esr_t esr;
+ mii_gsr_t gsr;
+ uint64_t val = 0;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_mii_read"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (xcvr_reg) {
+ case MII_BMCR:
+ PCS_REG_RD(handle, portn, PCS_MII_CTRL_REG, &val);
+ *value = (uint16_t)val;
+ break;
+ case MII_BMSR:
+ PCS_REG_RD(handle, portn, PCS_MII_STATUS_REG, &val);
+ pcs_stat.value = val;
+ PCS_REG_RD(handle, portn, PCS_STATE_MACHINE_REG, &val);
+ pcs_stat_mc.value = val;
+ if ((pcs_stat_mc.bits.w0.link_cfg_stat == 0xB) &&
+ (pcs_stat_mc.bits.w0.word_sync != 0)) {
+ pcs_stat.bits.w0.link_stat = 1;
+ } else if (pcs_stat_mc.bits.w0.link_cfg_stat != 0xB) {
+ pcs_stat.bits.w0.link_stat = 0;
+ }
+ *value = (uint16_t)pcs_stat.value;
+ break;
+ case MII_ESR:
+ PCS_REG_RD(handle, portn, PCS_MII_ADVERT_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ esr.value = 0;
+ esr.bits.link_1000fdx = pcs_anar.bits.w0.full_duplex;
+ esr.bits.link_1000hdx = pcs_anar.bits.w0.half_duplex;
+ *value = esr.value;
+ break;
+ case MII_ANAR:
+ PCS_REG_RD(handle, portn, PCS_MII_ADVERT_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ anar.value = 0;
+ anar.bits.cap_pause = pcs_anar.bits.w0.pause;
+ anar.bits.cap_asmpause = pcs_anar.bits.w0.asm_pause;
+ *value = anar.value;
+ break;
+ case MII_ANLPAR:
+ PCS_REG_RD(handle, portn, PCS_MII_LPA_REG, &val);
+ pcs_anlpar.value = (uint16_t)val;
+ anlpar.bits.cap_pause = pcs_anlpar.bits.w0.pause;
+ anlpar.bits.cap_asmpause = pcs_anlpar.bits.w0.asm_pause;
+ *value = anlpar.value;
+ break;
+ case MII_ANER:
+ PCS_REG_RD(handle, portn, PCS_MII_ADVERT_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ aner.value = 0;
+ aner.bits.lp_an_able = pcs_anar.bits.w0.full_duplex |
+ pcs_anar.bits.w0.half_duplex;
+ *value = aner.value;
+ break;
+ case MII_GSR:
+ PCS_REG_RD(handle, portn, PCS_MII_LPA_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ gsr.value = 0;
+ gsr.bits.link_1000fdx = pcs_anar.bits.w0.full_duplex;
+ gsr.bits.link_1000hdx = pcs_anar.bits.w0.half_duplex;
+ *value = gsr.value;
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_mii_read"
+ " Invalid Input: xcvr_reg <0x%x>",
+ xcvr_reg));
+ return (NPI_FAILURE | NPI_MAC_REG_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_pcs_mii_write(npi_handle_t handle, uint8_t portn, uint8_t xcvr_reg,
+ uint16_t value)
+{
+ pcs_anar_t pcs_anar;
+ mii_anar_t anar;
+ mii_gcr_t gcr;
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_mii_write"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ switch (xcvr_reg) {
+ case MII_BMCR:
+ val = (uint16_t)value;
+ PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, val);
+ break;
+ case MII_ANAR:
+ PCS_REG_RD(handle, portn, PCS_MII_ADVERT_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ anar.value = value;
+ pcs_anar.bits.w0.asm_pause = anar.bits.cap_asmpause;
+ pcs_anar.bits.w0.pause = anar.bits.cap_pause;
+ val = pcs_anar.value;
+ PCS_REG_WR(handle, portn, PCS_MII_ADVERT_REG, val);
+ break;
+ case MII_GCR:
+ PCS_REG_RD(handle, portn, PCS_MII_ADVERT_REG, &val);
+ pcs_anar.value = (uint16_t)val;
+ gcr.value = value;
+ pcs_anar.bits.w0.full_duplex = gcr.bits.link_1000fdx;
+ pcs_anar.bits.w0.half_duplex = gcr.bits.link_1000hdx;
+ val = pcs_anar.value;
+ PCS_REG_WR(handle, portn, PCS_MII_ADVERT_REG, val);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_pcs_mii_write"
+ " Invalid Input: xcvr_reg <0x%x>",
+ xcvr_reg));
+ return (NPI_FAILURE | NPI_MAC_REG_INVALID(portn));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_mac_mif_link_intr_enable(npi_handle_t handle, uint8_t portn,
+ uint8_t xcvr_reg, uint16_t mask)
+{
+ mif_cfg_t mif_cfg;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_mif_link_intr_enable"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ if (xcvr_reg > NXGE_MAX_MII_REGS) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_mac_mif_link_intr_enable"
+ " Invalid Input: xcvr_reg <0x%x>",
+ xcvr_reg));
+ return (NPI_FAILURE | NPI_MAC_REG_INVALID(portn));
+ }
+
+ MIF_REG_RD(handle, MIF_CONFIG_REG, &mif_cfg.value);
+
+ mif_cfg.bits.w0.phy_addr = portn; /* Port number */
+ mif_cfg.bits.w0.reg_addr = xcvr_reg; /* Register address */
+ mif_cfg.bits.w0.indirect_md = 0; /* Clause 22 */
+ mif_cfg.bits.w0.poll_en = 1;
+
+ MIF_REG_WR(handle, MIF_MASK_REG, ~mask);
+ MIF_REG_WR(handle, MIF_CONFIG_REG, mif_cfg.value);
+
+ NXGE_DELAY(20);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_mac_mif_mdio_link_intr_enable(npi_handle_t handle, uint8_t portn,
+ uint8_t device, uint16_t xcvr_reg, uint16_t mask)
+{
+ mif_cfg_t mif_cfg;
+ mif_frame_t frame;
+ uint_t delay;
+
+ if (!IS_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_mac_mif_mdio_poll_enable"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ frame.bits.w0.st = 0; /* Clause 45 */
+ frame.bits.w0.op = 0; /* Select address */
+ frame.bits.w0.phyad = portn; /* Port number */
+ frame.bits.w0.regad = device; /* Device number */
+ frame.bits.w0.ta_msb = 1;
+ frame.bits.w0.ta_lsb = 0;
+ frame.bits.w0.data = xcvr_reg; /* register address */
+
+ MIF_REG_WR(handle, MIF_OUTPUT_FRAME_REG, frame.value);
+
+ delay = 0;
+ do {
+ NXGE_DELAY(500);
+ MIF_REG_RD(handle, MIF_OUTPUT_FRAME_REG, &frame.value)
+ delay++;
+ } while ((frame.bits.w0.ta_lsb == 0) && (delay < MAX_PIO_RETRIES));
+
+ if (delay == MAX_PIO_RETRIES)
+ return (NPI_FAILURE);
+
+ MIF_REG_RD(handle, MIF_CONFIG_REG, &mif_cfg.value);
+
+ mif_cfg.bits.w0.phy_addr = portn; /* Port number */
+ mif_cfg.bits.w0.reg_addr = device; /* Register address */
+ mif_cfg.bits.w0.indirect_md = 1; /* Clause 45 */
+ mif_cfg.bits.w0.poll_en = 1;
+
+ MIF_REG_WR(handle, MIF_MASK_REG, ~mask);
+ MIF_REG_WR(handle, MIF_CONFIG_REG, mif_cfg.value);
+
+ NXGE_DELAY(20);
+
+ return (NPI_SUCCESS);
+}
+
+void
+npi_mac_mif_set_indirect_mode(npi_handle_t handle, boolean_t on_off)
+{
+ mif_cfg_t mif_cfg;
+
+ MIF_REG_RD(handle, MIF_CONFIG_REG, &mif_cfg.value);
+ mif_cfg.bits.w0.indirect_md = on_off;
+ MIF_REG_WR(handle, MIF_CONFIG_REG, mif_cfg.value);
+}
+
+npi_status_t
+npi_bmac_send_pause(npi_handle_t handle, uint8_t portn, uint16_t pause_time)
+{
+ uint64_t val;
+
+ if (!IS_BMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_bmac_send_pause"
+ " Invalid Input: portn <%d>",
+ portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ val = MAC_SEND_PAUSE_SEND | pause_time;
+ BMAC_REG_WR(handle, portn, MAC_SEND_PAUSE_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_xif_led(npi_handle_t handle, uint8_t portn, boolean_t on_off)
+{
+ uint64_t val = 0;
+
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_led"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+
+ if (on_off == B_TRUE) {
+ val |= XMAC_XIF_LED_POLARITY;
+ val &= ~XMAC_XIF_FORCE_LED_ON;
+ } else {
+ val &= ~XMAC_XIF_LED_POLARITY;
+ val |= XMAC_XIF_FORCE_LED_ON;
+ }
+
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_zap_tx_counters(npi_handle_t handle, uint8_t portn)
+{
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_zap_tx_counters"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_WR(handle, portn, XTXMAC_FRM_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XTXMAC_BYTE_CNT_REG, 0);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_xmac_zap_rx_counters(npi_handle_t handle, uint8_t portn)
+{
+ if (!IS_XMAC_PORT_NUM_VALID(portn)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_xmac_zap_rx_counters"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_MAC_PORT_INVALID(portn));
+ }
+
+ XMAC_REG_WR(handle, portn, XRXMAC_BT_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_BC_FRM_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_MC_FRM_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_FRAG_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT1_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT2_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT3_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT4_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT5_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_HIST_CNT6_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_MPSZER_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_CRC_ER_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_CD_VIO_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XRXMAC_AL_ER_CNT_REG, 0);
+ XMAC_REG_WR(handle, portn, XMAC_LINK_FLT_CNT_REG, 0);
+
+ return (NPI_SUCCESS);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_mac.h b/usr/src/uts/sun4v/io/nxge/npi/npi_mac.h
new file mode 100644
index 0000000000..06f0b80ef2
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_mac.h
@@ -0,0 +1,573 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_MAC_H
+#define _NPI_MAC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_mac_hw.h>
+#include <nxge_mii.h>
+
+typedef struct _npi_mac_addr {
+ uint16_t w0;
+ uint16_t w1;
+ uint16_t w2;
+} npi_mac_addr_t;
+
+typedef enum npi_mac_attr {
+ MAC_PORT_MODE = 0,
+ MAC_PORT_FRAME_SIZE,
+ MAC_PORT_ADDR,
+ MAC_PORT_ADDR_FILTER,
+ MAC_PORT_ADDR_FILTER_MASK,
+ XMAC_PORT_IPG,
+ XMAC_10G_PORT_IPG,
+ BMAC_PORT_MAX_BURST_SIZE,
+ BMAC_PORT_PA_SIZE,
+ BMAC_PORT_CTRL_TYPE
+} npi_mac_attr_t;
+
+/* MAC Mode options */
+
+typedef enum npi_mac_mode_e {
+ MAC_MII_MODE = 0,
+ MAC_GMII_MODE,
+ MAC_XGMII_MODE
+} npi_mac_mode_t;
+
+typedef enum npi_mac_reset_e {
+ TX_MAC_RESET = 1,
+ RX_MAC_RESET,
+ XTX_MAC_REG_RESET,
+ XRX_MAC_REG_RESET,
+ XTX_MAC_LOGIC_RESET,
+ XRX_MAC_LOGIC_RESET,
+ XTX_MAC_RESET_ALL,
+ XRX_MAC_RESET_ALL,
+ BMAC_RESET_ALL,
+ XMAC_RESET_ALL
+} npi_mac_reset_t;
+
+typedef enum xmac_tx_iconfig_e {
+ ICFG_XMAC_TX_FRAME_XMIT = XMAC_TX_FRAME_XMIT,
+ ICFG_XMAC_TX_UNDERRUN = XMAC_TX_UNDERRUN,
+ ICFG_XMAC_TX_MAX_PACKET_ERR = XMAC_TX_MAX_PACKET_ERR,
+ ICFG_XMAC_TX_OVERFLOW = XMAC_TX_OVERFLOW,
+ ICFG_XMAC_TX_FIFO_XFR_ERR = XMAC_TX_FIFO_XFR_ERR,
+ ICFG_XMAC_TX_BYTE_CNT_EXP = XMAC_TX_BYTE_CNT_EXP,
+ ICFG_XMAC_TX_FRAME_CNT_EXP = XMAC_TX_FRAME_CNT_EXP,
+ ICFG_XMAC_TX_ALL = (XMAC_TX_FRAME_XMIT | XMAC_TX_UNDERRUN |
+ XMAC_TX_MAX_PACKET_ERR | XMAC_TX_OVERFLOW |
+ XMAC_TX_FIFO_XFR_ERR | XMAC_TX_BYTE_CNT_EXP |
+ XMAC_TX_FRAME_CNT_EXP)
+} xmac_tx_iconfig_t;
+
+typedef enum xmac_rx_iconfig_e {
+ ICFG_XMAC_RX_FRAME_RCVD = XMAC_RX_FRAME_RCVD,
+ ICFG_XMAC_RX_OVERFLOW = XMAC_RX_OVERFLOW,
+ ICFG_XMAC_RX_UNDERFLOW = XMAC_RX_UNDERFLOW,
+ ICFG_XMAC_RX_CRC_ERR_CNT_EXP = XMAC_RX_CRC_ERR_CNT_EXP,
+ ICFG_XMAC_RX_LEN_ERR_CNT_EXP = XMAC_RX_LEN_ERR_CNT_EXP,
+ ICFG_XMAC_RX_VIOL_ERR_CNT_EXP = XMAC_RX_VIOL_ERR_CNT_EXP,
+ ICFG_XMAC_RX_OCT_CNT_EXP = XMAC_RX_OCT_CNT_EXP,
+ ICFG_XMAC_RX_HST_CNT1_EXP = XMAC_RX_HST_CNT1_EXP,
+ ICFG_XMAC_RX_HST_CNT2_EXP = XMAC_RX_HST_CNT2_EXP,
+ ICFG_XMAC_RX_HST_CNT3_EXP = XMAC_RX_HST_CNT3_EXP,
+ ICFG_XMAC_RX_HST_CNT4_EXP = XMAC_RX_HST_CNT4_EXP,
+ ICFG_XMAC_RX_HST_CNT5_EXP = XMAC_RX_HST_CNT5_EXP,
+ ICFG_XMAC_RX_HST_CNT6_EXP = XMAC_RX_HST_CNT6_EXP,
+ ICFG_XMAC_RX_BCAST_CNT_EXP = XMAC_RX_BCAST_CNT_EXP,
+ ICFG_XMAC_RX_MCAST_CNT_EXP = XMAC_RX_MCAST_CNT_EXP,
+ ICFG_XMAC_RX_FRAG_CNT_EXP = XMAC_RX_FRAG_CNT_EXP,
+ ICFG_XMAC_RX_ALIGNERR_CNT_EXP = XMAC_RX_ALIGNERR_CNT_EXP,
+ ICFG_XMAC_RX_LINK_FLT_CNT_EXP = XMAC_RX_LINK_FLT_CNT_EXP,
+ ICFG_XMAC_RX_HST_CNT7_EXP = XMAC_RX_HST_CNT7_EXP,
+ ICFG_XMAC_RX_REMOTE_FLT_DET = XMAC_RX_REMOTE_FLT_DET,
+ ICFG_XMAC_RX_LOCAL_FLT_DET = XMAC_RX_LOCAL_FLT_DET,
+ ICFG_XMAC_RX_ALL = (XMAC_RX_FRAME_RCVD | XMAC_RX_OVERFLOW |
+ XMAC_RX_UNDERFLOW | XMAC_RX_CRC_ERR_CNT_EXP |
+ XMAC_RX_LEN_ERR_CNT_EXP |
+ XMAC_RX_VIOL_ERR_CNT_EXP |
+ XMAC_RX_OCT_CNT_EXP | XMAC_RX_HST_CNT1_EXP |
+ XMAC_RX_HST_CNT2_EXP | XMAC_RX_HST_CNT3_EXP |
+ XMAC_RX_HST_CNT4_EXP | XMAC_RX_HST_CNT5_EXP |
+ XMAC_RX_HST_CNT6_EXP | XMAC_RX_BCAST_CNT_EXP |
+ XMAC_RX_MCAST_CNT_EXP | XMAC_RX_FRAG_CNT_EXP |
+ XMAC_RX_ALIGNERR_CNT_EXP |
+ XMAC_RX_LINK_FLT_CNT_EXP |
+ XMAC_RX_HST_CNT7_EXP |
+ XMAC_RX_REMOTE_FLT_DET | XMAC_RX_LOCAL_FLT_DET)
+} xmac_rx_iconfig_t;
+
+typedef enum xmac_ctl_iconfig_e {
+ ICFG_XMAC_CTRL_PAUSE_RCVD = XMAC_CTRL_PAUSE_RCVD,
+ ICFG_XMAC_CTRL_PAUSE_STATE = XMAC_CTRL_PAUSE_STATE,
+ ICFG_XMAC_CTRL_NOPAUSE_STATE = XMAC_CTRL_NOPAUSE_STATE,
+ ICFG_XMAC_CTRL_ALL = (XMAC_CTRL_PAUSE_RCVD | XMAC_CTRL_PAUSE_STATE |
+ XMAC_CTRL_NOPAUSE_STATE)
+} xmac_ctl_iconfig_t;
+
+
+typedef enum bmac_tx_iconfig_e {
+ ICFG_BMAC_TX_FRAME_SENT = MAC_TX_FRAME_XMIT,
+ ICFG_BMAC_TX_UNDERFLOW = MAC_TX_UNDERRUN,
+ ICFG_BMAC_TX_MAXPKTSZ_ERR = MAC_TX_MAX_PACKET_ERR,
+ ICFG_BMAC_TX_BYTE_CNT_EXP = MAC_TX_BYTE_CNT_EXP,
+ ICFG_BMAC_TX_FRAME_CNT_EXP = MAC_TX_FRAME_CNT_EXP,
+ ICFG_BMAC_TX_ALL = (MAC_TX_FRAME_XMIT | MAC_TX_UNDERRUN |
+ MAC_TX_MAX_PACKET_ERR | MAC_TX_BYTE_CNT_EXP |
+ MAC_TX_FRAME_CNT_EXP)
+} bmac_tx_iconfig_t;
+
+typedef enum bmac_rx_iconfig_e {
+ ICFG_BMAC_RX_FRAME_RCVD = MAC_RX_FRAME_RECV,
+ ICFG_BMAC_RX_OVERFLOW = MAC_RX_OVERFLOW,
+ ICFG_BMAC_RX_FRAME_CNT_EXP = MAC_RX_FRAME_COUNT,
+ ICFG_BMAC_RX_CRC_ERR_CNT_EXP = MAC_RX_ALIGN_ERR,
+ ICFG_BMAC_RX_LEN_ERR_CNT_EXP = MAC_RX_CRC_ERR,
+ ICFG_BMAC_RX_VIOL_ERR_CNT_EXP = MAC_RX_LEN_ERR,
+ ICFG_BMAC_RX_BYTE_CNT_EXP = MAC_RX_VIOL_ERR,
+ ICFG_BMAC_RX_ALIGNERR_CNT_EXP = MAC_RX_BYTE_CNT_EXP,
+ ICFG_BMAC_RX_ALL = (MAC_RX_FRAME_RECV | MAC_RX_OVERFLOW |
+ MAC_RX_FRAME_COUNT | MAC_RX_ALIGN_ERR |
+ MAC_RX_CRC_ERR | MAC_RX_LEN_ERR |
+ MAC_RX_VIOL_ERR | MAC_RX_BYTE_CNT_EXP)
+} bmac_rx_iconfig_t;
+
+typedef enum bmac_ctl_iconfig_e {
+ ICFG_BMAC_CTL_RCVPAUSE = MAC_CTRL_PAUSE_RECEIVED,
+ ICFG_BMAC_CTL_INPAUSE_ST = MAC_CTRL_PAUSE_STATE,
+ ICFG_BMAC_CTL_INNOTPAUSE_ST = MAC_CTRL_NOPAUSE_STATE,
+ ICFG_BMAC_CTL_ALL = (MAC_CTRL_PAUSE_RECEIVED | MAC_CTRL_PAUSE_STATE |
+ MAC_CTRL_NOPAUSE_STATE)
+} bmac_ctl_iconfig_t;
+
+typedef enum xmac_tx_config_e {
+ CFG_XMAC_TX = 0x00000001,
+ CFG_XMAC_TX_STRETCH_MODE = 0x00000002,
+ CFG_XMAC_VAR_IPG = 0x00000004,
+ CFG_XMAC_TX_CRC = 0x00000008,
+ CFG_XMAC_TX_ALL = 0x0000000F
+} xmac_tx_config_t;
+
+typedef enum xmac_rx_config_e {
+ CFG_XMAC_RX = 0x00000001,
+ CFG_XMAC_RX_PROMISCUOUS = 0x00000002,
+ CFG_XMAC_RX_PROMISCUOUSGROUP = 0x00000004,
+ CFG_XMAC_RX_ERRCHK = 0x00000008,
+ CFG_XMAC_RX_CRC_CHK = 0x00000010,
+ CFG_XMAC_RX_RESV_MULTICAST = 0x00000020,
+ CFG_XMAC_RX_CODE_VIO_CHK = 0x00000040,
+ CFG_XMAC_RX_HASH_FILTER = 0x00000080,
+ CFG_XMAC_RX_ADDR_FILTER = 0x00000100,
+ CFG_XMAC_RX_STRIP_CRC = 0x00000200,
+ CFG_XMAC_RX_PAUSE = 0x00000400,
+ CFG_XMAC_RX_PASS_FC_FRAME = 0x00000800,
+ CFG_XMAC_RX_MAC2IPP_PKT_CNT = 0x00001000,
+ CFG_XMAC_RX_ALL = 0x00001FFF
+} xmac_rx_config_t;
+
+typedef enum xmac_xif_config_e {
+ CFG_XMAC_XIF_LED_FORCE = 0x00000001,
+ CFG_XMAC_XIF_LED_POLARITY = 0x00000002,
+ CFG_XMAC_XIF_SEL_POR_CLK_SRC = 0x00000004,
+ CFG_XMAC_XIF_TX_OUTPUT = 0x00000008,
+ CFG_XMAC_XIF_LOOPBACK = 0x00000010,
+ CFG_XMAC_XIF_LFS = 0x00000020,
+ CFG_XMAC_XIF_XPCS_BYPASS = 0x00000040,
+ CFG_XMAC_XIF_1G_PCS_BYPASS = 0x00000080,
+ CFG_XMAC_XIF_SEL_CLK_25MHZ = 0x00000100,
+ CFG_XMAC_XIF_ALL = 0x000001FF
+} xmac_xif_config_t;
+
+typedef enum bmac_tx_config_e {
+ CFG_BMAC_TX = 0x00000001,
+ CFG_BMAC_TX_CRC = 0x00000002,
+ CFG_BMAC_TX_ALL = 0x00000003
+} bmac_tx_config_t;
+
+typedef enum bmac_rx_config_e {
+ CFG_BMAC_RX = 0x00000001,
+ CFG_BMAC_RX_STRIP_PAD = 0x00000002,
+ CFG_BMAC_RX_STRIP_CRC = 0x00000004,
+ CFG_BMAC_RX_PROMISCUOUS = 0x00000008,
+ CFG_BMAC_RX_PROMISCUOUSGROUP = 0x00000010,
+ CFG_BMAC_RX_HASH_FILTER = 0x00000020,
+ CFG_BMAC_RX_ADDR_FILTER = 0x00000040,
+ CFG_BMAC_RX_DISCARD_ON_ERR = 0x00000080,
+ CFG_BMAC_RX_ALL = 0x000000FF
+} bmac_rx_config_t;
+
+typedef enum bmac_xif_config_e {
+ CFG_BMAC_XIF_TX_OUTPUT = 0x00000001,
+ CFG_BMAC_XIF_LOOPBACK = 0x00000002,
+ CFG_BMAC_XIF_GMII_MODE = 0x00000008,
+ CFG_BMAC_XIF_LINKLED = 0x00000020,
+ CFG_BMAC_XIF_LED_POLARITY = 0x00000040,
+ CFG_BMAC_XIF_SEL_CLK_25MHZ = 0x00000080,
+ CFG_BMAC_XIF_ALL = 0x000000FF
+} bmac_xif_config_t;
+
+
+typedef enum xmac_ipg_e {
+ XGMII_IPG_12_15 = 0,
+ XGMII_IPG_16_19,
+ XGMII_IPG_20_23,
+ MII_GMII_IPG_12,
+ MII_GMII_IPG_13,
+ MII_GMII_IPG_14,
+ MII_GMII_IPG_15,
+ MII_GMII_IPG_16
+} xmac_ipg_t;
+
+typedef enum xpcs_reg_e {
+ XPCS_REG_CONTROL1,
+ XPCS_REG_STATUS1,
+ XPCS_REG_DEVICE_ID,
+ XPCS_REG_SPEED_ABILITY,
+ XPCS_REG_DEVICE_IN_PKG,
+ XPCS_REG_CONTROL2,
+ XPCS_REG_STATUS2,
+ XPCS_REG_PKG_ID,
+ XPCS_REG_STATUS,
+ XPCS_REG_TEST_CONTROL,
+ XPCS_REG_CONFIG_VENDOR1,
+ XPCS_REG_DIAG_VENDOR2,
+ XPCS_REG_MASK1,
+ XPCS_REG_PACKET_COUNTER,
+ XPCS_REG_TX_STATEMACHINE,
+ XPCS_REG_DESCWERR_COUNTER,
+ XPCS_REG_SYMBOL_ERR_L0_1_COUNTER,
+ XPCS_REG_SYMBOL_ERR_L2_3_COUNTER,
+ XPCS_REG_TRAINING_VECTOR
+} xpcs_reg_t;
+
+#define IS_XMAC_PORT_NUM_VALID(portn)\
+ ((portn == XMAC_PORT_0) || (portn == XMAC_PORT_1))
+
+#define IS_BMAC_PORT_NUM_VALID(portn)\
+ ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
+
+#define XMAC_REG_WR(handle, portn, reg, val)\
+ NXGE_REG_WR64(handle, XMAC_REG_ADDR((portn), (reg)), (val))
+
+#define XMAC_REG_RD(handle, portn, reg, val_p)\
+ NXGE_REG_RD64(handle, XMAC_REG_ADDR((portn), (reg)), (val_p))
+
+#define BMAC_REG_WR(handle, portn, reg, val)\
+ NXGE_REG_WR64(handle, BMAC_REG_ADDR((portn), (reg)), (val))
+
+#define BMAC_REG_RD(handle, portn, reg, val_p)\
+ NXGE_REG_RD64(handle, BMAC_REG_ADDR((portn), (reg)), (val_p))
+
+#define PCS_REG_WR(handle, portn, reg, val)\
+ NXGE_REG_WR64(handle, PCS_REG_ADDR((portn), (reg)), (val))
+
+#define PCS_REG_RD(handle, portn, reg, val_p)\
+ NXGE_REG_RD64(handle, PCS_REG_ADDR((portn), (reg)), (val_p))
+
+#define XPCS_REG_WR(handle, portn, reg, val)\
+ NXGE_REG_WR64(handle, XPCS_ADDR((portn), (reg)), (val))
+
+#define XPCS_REG_RD(handle, portn, reg, val_p)\
+ NXGE_REG_RD64(handle, XPCS_ADDR((portn), (reg)), (val_p))
+
+#define MIF_REG_WR(handle, reg, val)\
+ NXGE_REG_WR64(handle, MIF_ADDR((reg)), (val))
+
+#define MIF_REG_RD(handle, reg, val_p)\
+ NXGE_REG_RD64(handle, MIF_ADDR((reg)), (val_p))
+
+
+/*
+ * When MIF_REG_RD is called inside a poll loop and if the poll takes
+ * very long time to complete, then each poll will print a rt_show_reg
+ * result on the screen and the rtrace "register show" result may
+ * become too messy to read. The solution is to call MIF_REG_RD_NO_SHOW
+ * instead of MIF_REG_RD in a polling loop. When COSIM or REG_SHOW is
+ * not defined, this macro is the same as MIF_REG_RD. When both COSIM
+ * and REG_SHOW are defined, this macro calls NXGE_REG_RD64_NO_SHOW
+ * which does not call rt_show_reg.
+ */
+#if defined(COSIM) && defined(REG_SHOW)
+#define MIF_REG_RD_NO_SHOW(handle, reg, val_p)\
+ NXGE_REG_RD64_NO_SHOW(handle, MIF_ADDR((reg)), (val_p))
+#else
+ /* If not COSIM or REG_SHOW, still show */
+#define MIF_REG_RD_NO_SHOW(handle, reg, val_p)\
+ NXGE_REG_RD64(handle, MIF_ADDR((reg)), (val_p))
+#endif
+
+#define ESR_REG_WR(handle, reg, val)\
+ NXGE_REG_WR64(handle, ESR_ADDR((reg)), (val))
+
+#define ESR_REG_RD(handle, reg, val_p)\
+ NXGE_REG_RD64(handle, ESR_ADDR((reg)), (val_p))
+
+/* Macros to read/modify MAC attributes */
+
+#define SET_MAC_ATTR1(handle, p, portn, attr, val, stat) {\
+ p.type = attr;\
+ p.idata[0] = (uint32_t)val;\
+ stat = npi_mac_port_attr(handle, OP_SET, portn, (npi_attr_t *)&p);\
+}
+
+#define SET_MAC_ATTR2(handle, p, portn, attr, val0, val1, stat) {\
+ p.type = attr;\
+ p.idata[0] = (uint32_t)val0;\
+ p.idata[1] = (uint32_t)val1;\
+ stat = npi_mac_port_attr(handle, OP_SET, portn, (npi_attr_t *)&p);\
+}
+
+#define SET_MAC_ATTR3(handle, p, portn, attr, val0, val1, val2, stat) {\
+ p.type = attr;\
+ p.idata[0] = (uint32_t)val0;\
+ p.idata[1] = (uint32_t)val1;\
+ p.idata[2] = (uint32_t)val2;\
+ stat = npi_mac_port_attr(handle, OP_SET, portn, (npi_attr_t *)&p);\
+}
+
+#define SET_MAC_ATTR4(handle, p, portn, attr, val0, val1, val2, val3, stat) {\
+ p.type = attr;\
+ p.idata[0] = (uint32_t)val0;\
+ p.idata[1] = (uint32_t)val1;\
+ p.idata[2] = (uint32_t)val2;\
+ p.idata[3] = (uint32_t)val3;\
+ stat = npi_mac_port_attr(handle, OP_SET, portn, (npi_attr_t *)&p);\
+}
+
+#define GET_MAC_ATTR1(handle, p, portn, attr, val, stat) {\
+ p.type = attr;\
+ if ((stat = npi_mac_port_attr(handle, OP_GET, portn, \
+ (npi_attr_t *)&p)) == NPI_SUCCESS) {\
+ val = p.odata[0];\
+ }\
+}
+
+#define GET_MAC_ATTR2(handle, p, portn, attr, val0, val1, stat) {\
+ p.type = attr;\
+ if ((stat = npi_mac_port_attr(handle, OP_GET, portn, \
+ (npi_attr_t *)&p)) == NPI_SUCCESS) {\
+ val0 = p.odata[0];\
+ val1 = p.odata[1];\
+ }\
+}
+
+#define GET_MAC_ATTR3(handle, p, portn, attr, val0, val1, \
+ val2, stat) {\
+ p.type = attr;\
+ if ((stat = npi_mac_port_attr(handle, OP_GET, portn, \
+ (npi_attr_t *)&p)) == NPI_SUCCESS) {\
+ val0 = p.odata[0];\
+ val1 = p.odata[1];\
+ val2 = p.odata[2];\
+ }\
+}
+
+#define GET_MAC_ATTR4(handle, p, portn, attr, val0, val1, \
+ val2, val3, stat) {\
+ p.type = attr;\
+ if ((stat = npi_mac_port_attr(handle, OP_GET, portn, \
+ (npi_attr_t *)&p)) == NPI_SUCCESS) {\
+ val0 = p.odata[0];\
+ val1 = p.odata[1];\
+ val2 = p.odata[2];\
+ val3 = p.odata[3];\
+ }\
+}
+
+/* MAC specific errors */
+
+#define MAC_PORT_ATTR_INVALID 0x50
+#define MAC_RESET_MODE_INVALID 0x51
+#define MAC_HASHTAB_ENTRY_INVALID 0x52
+#define MAC_HOSTINFO_ENTRY_INVALID 0x53
+#define MAC_ALT_ADDR_ENTRY_INVALID 0x54
+
+/* MAC error return macros */
+
+#define NPI_MAC_PORT_INVALID(portn) ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ PORT_INVALID | IS_PORT | (portn << 12))
+#define NPI_MAC_OPCODE_INVALID(portn) ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ OPCODE_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_HASHTAB_ENTRY_INVALID(portn)\
+ ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ MAC_HASHTAB_ENTRY_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_HOSTINFO_ENTRY_INVALID(portn)\
+ ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ MAC_HOSTINFO_ENTRY_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_ALT_ADDR_ENTRY_INVALID(portn)\
+ ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ MAC_ALT_ADDR_ENTRY_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_PORT_ATTR_INVALID(portn)\
+ ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ MAC_PORT_ATTR_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_RESET_MODE_INVALID(portn)\
+ ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ MAC_RESET_MODE_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_PCS_REG_INVALID(portn) ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ REGISTER_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_TXMAC_RESET_FAILED(portn) ((TXMAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ RESET_FAILED | IS_PORT | (portn << 12))
+#define NPI_RXMAC_RESET_FAILED(portn) ((RXMAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ RESET_FAILED | IS_PORT | (portn << 12))
+#define NPI_MAC_CONFIG_INVALID(portn) ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ CONFIG_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_REG_INVALID(portn) ((MAC_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ REGISTER_INVALID |\
+ IS_PORT | (portn << 12))
+#define NPI_MAC_MII_READ_FAILED(portn) ((MIF_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ READ_FAILED | IS_PORT | (portn << 12))
+#define NPI_MAC_MII_WRITE_FAILED(portn) ((MIF_BLK_ID << NPI_BLOCK_ID_SHIFT) |\
+ WRITE_FAILED | IS_PORT | (portn << 12))
+
+/* library functions prototypes */
+
+/* general mac functions */
+npi_status_t npi_mac_hashtab_entry(npi_handle_t, io_op_t,
+ uint8_t, uint8_t, uint16_t *);
+npi_status_t npi_mac_hostinfo_entry(npi_handle_t, io_op_t,
+ uint8_t, uint8_t,
+ hostinfo_t *);
+npi_status_t npi_mac_altaddr_enable(npi_handle_t, uint8_t,
+ uint8_t);
+npi_status_t npi_mac_altaddr_disble(npi_handle_t, uint8_t,
+ uint8_t);
+npi_status_t npi_mac_altaddr_entry(npi_handle_t, io_op_t,
+ uint8_t, uint8_t,
+ npi_mac_addr_t *);
+npi_status_t npi_mac_port_attr(npi_handle_t, io_op_t, uint8_t,
+ npi_attr_t *);
+npi_status_t npi_mac_get_link_status(npi_handle_t, uint8_t,
+ boolean_t *);
+npi_status_t npi_mac_get_10g_link_status(npi_handle_t, uint8_t,
+ boolean_t *);
+npi_status_t npi_mac_mif_mii_read(npi_handle_t, uint8_t,
+ uint8_t, uint16_t *);
+npi_status_t npi_mac_mif_mii_write(npi_handle_t, uint8_t,
+ uint8_t, uint16_t);
+npi_status_t npi_mac_mif_link_intr_enable(npi_handle_t, uint8_t,
+ uint8_t, uint16_t);
+npi_status_t npi_mac_mif_mdio_read(npi_handle_t, uint8_t,
+ uint8_t, uint16_t,
+ uint16_t *);
+npi_status_t npi_mac_mif_mdio_write(npi_handle_t, uint8_t,
+ uint8_t, uint16_t,
+ uint16_t);
+npi_status_t npi_mac_mif_mdio_link_intr_enable(npi_handle_t,
+ uint8_t, uint8_t,
+ uint16_t, uint16_t);
+npi_status_t npi_mac_mif_link_intr_disable(npi_handle_t, uint8_t);
+npi_status_t npi_mac_pcs_mii_read(npi_handle_t, uint8_t,
+ uint8_t, uint16_t *);
+npi_status_t npi_mac_pcs_mii_write(npi_handle_t, uint8_t,
+ uint8_t, uint16_t);
+npi_status_t npi_mac_pcs_link_intr_enable(npi_handle_t, uint8_t);
+npi_status_t npi_mac_pcs_link_intr_disable(npi_handle_t, uint8_t);
+npi_status_t npi_mac_pcs_reset(npi_handle_t, uint8_t);
+
+/* xmac functions */
+npi_status_t npi_xmac_reset(npi_handle_t, uint8_t,
+ npi_mac_reset_t);
+npi_status_t npi_xmac_xif_config(npi_handle_t, config_op_t,
+ uint8_t, xmac_xif_config_t);
+npi_status_t npi_xmac_tx_config(npi_handle_t, config_op_t,
+ uint8_t, xmac_tx_config_t);
+npi_status_t npi_xmac_rx_config(npi_handle_t, config_op_t,
+ uint8_t, xmac_rx_config_t);
+npi_status_t npi_xmac_tx_iconfig(npi_handle_t, config_op_t,
+ uint8_t, xmac_tx_iconfig_t);
+npi_status_t npi_xmac_rx_iconfig(npi_handle_t, config_op_t,
+ uint8_t, xmac_rx_iconfig_t);
+npi_status_t npi_xmac_ctl_iconfig(npi_handle_t, config_op_t,
+ uint8_t, xmac_ctl_iconfig_t);
+npi_status_t npi_xmac_tx_get_istatus(npi_handle_t, uint8_t,
+ xmac_tx_iconfig_t *);
+npi_status_t npi_xmac_rx_get_istatus(npi_handle_t, uint8_t,
+ xmac_rx_iconfig_t *);
+npi_status_t npi_xmac_ctl_get_istatus(npi_handle_t, uint8_t,
+ xmac_ctl_iconfig_t *);
+npi_status_t npi_xmac_xpcs_reset(npi_handle_t, uint8_t);
+npi_status_t npi_xmac_xpcs_enable(npi_handle_t, uint8_t);
+npi_status_t npi_xmac_xpcs_disable(npi_handle_t, uint8_t);
+npi_status_t npi_xmac_xpcs_read(npi_handle_t, uint8_t,
+ uint8_t, uint32_t *);
+npi_status_t npi_xmac_xpcs_write(npi_handle_t, uint8_t,
+ uint8_t, uint32_t);
+npi_status_t npi_xmac_xpcs_link_intr_enable(npi_handle_t, uint8_t);
+npi_status_t npi_xmac_xpcs_link_intr_disable(npi_handle_t,
+ uint8_t);
+npi_status_t npi_xmac_xif_led(npi_handle_t, uint8_t,
+ boolean_t);
+npi_status_t npi_xmac_zap_tx_counters(npi_handle_t, uint8_t);
+npi_status_t npi_xmac_zap_rx_counters(npi_handle_t, uint8_t);
+
+/* bmac functions */
+npi_status_t npi_bmac_reset(npi_handle_t, uint8_t,
+ npi_mac_reset_t mode);
+npi_status_t npi_bmac_tx_config(npi_handle_t, config_op_t,
+ uint8_t, bmac_tx_config_t);
+npi_status_t npi_bmac_rx_config(npi_handle_t, config_op_t,
+ uint8_t, bmac_rx_config_t);
+npi_status_t npi_bmac_rx_iconfig(npi_handle_t, config_op_t,
+ uint8_t, bmac_rx_iconfig_t);
+npi_status_t npi_bmac_xif_config(npi_handle_t, config_op_t,
+ uint8_t, bmac_xif_config_t);
+npi_status_t npi_bmac_tx_iconfig(npi_handle_t, config_op_t,
+ uint8_t, bmac_tx_iconfig_t);
+npi_status_t npi_bmac_ctl_iconfig(npi_handle_t, config_op_t,
+ uint8_t, bmac_ctl_iconfig_t);
+npi_status_t npi_bmac_tx_get_istatus(npi_handle_t, uint8_t,
+ bmac_tx_iconfig_t *);
+npi_status_t npi_bmac_rx_get_istatus(npi_handle_t, uint8_t,
+ bmac_rx_iconfig_t *);
+npi_status_t npi_bmac_ctl_get_istatus(npi_handle_t, uint8_t,
+ bmac_ctl_iconfig_t *);
+npi_status_t npi_bmac_send_pause(npi_handle_t, uint8_t,
+ uint16_t);
+npi_status_t npi_mac_dump_regs(npi_handle_t, uint8_t);
+
+/* MIF common functions */
+void npi_mac_mif_set_indirect_mode(npi_handle_t, boolean_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_MAC_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.c b/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.c
new file mode 100644
index 0000000000..8d6adf679a
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.c
@@ -0,0 +1,2347 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_rxdma.h>
+#include <nxge_common.h>
+
+#define RXDMA_RESET_TRY_COUNT 4
+#define RXDMA_RESET_DELAY 5
+
+#define RXDMA_OP_DISABLE 0
+#define RXDMA_OP_ENABLE 1
+#define RXDMA_OP_RESET 2
+
+#define RCR_TIMEOUT_ENABLE 1
+#define RCR_TIMEOUT_DISABLE 2
+#define RCR_THRESHOLD 4
+
+
+
+uint64_t rdc_dmc_offset[] = {
+ RXDMA_CFIG1_REG, RXDMA_CFIG2_REG, RBR_CFIG_A_REG, RBR_CFIG_B_REG,
+ RBR_KICK_REG, RBR_STAT_REG, RBR_HDH_REG, RBR_HDL_REG,
+ RCRCFIG_A_REG, RCRCFIG_B_REG, RCRSTAT_A_REG, RCRSTAT_B_REG,
+ RCRSTAT_C_REG, RX_DMA_ENT_MSK_REG, RX_DMA_CTL_STAT_REG, RCR_FLSH_REG,
+ RXMISC_DISCARD_REG
+};
+
+const char *rdc_dmc_name[] = {
+ "RXDMA_CFIG1", "RXDMA_CFIG2", "RBR_CFIG_A", "RBR_CFIG_B",
+ "RBR_KICK", "RBR_STAT", "RBR_HDH", "RBR_HDL",
+ "RCRCFIG_A", "RCRCFIG_B", "RCRSTAT_A", "RCRSTAT_B",
+ "RCRSTAT_C", "RX_DMA_ENT_MSK", "RX_DMA_CTL_STAT", "RCR_FLSH",
+ "RXMISC_DISCARD"
+};
+
+uint64_t rdc_fzc_offset [] = {
+ RX_LOG_PAGE_VLD_REG, RX_LOG_PAGE_MASK1_REG, RX_LOG_PAGE_VAL1_REG,
+ RX_LOG_PAGE_MASK2_REG, RX_LOG_PAGE_VAL2_REG, RX_LOG_PAGE_RELO1_REG,
+ RX_LOG_PAGE_RELO2_REG, RX_LOG_PAGE_HDL_REG, RDC_RED_PARA_REG,
+ RED_DIS_CNT_REG
+};
+
+
+const char *rdc_fzc_name [] = {
+ "RX_LOG_PAGE_VLD", "RX_LOG_PAGE_MASK1", "RX_LOG_PAGE_VAL1",
+ "RX_LOG_PAGE_MASK2", "RX_LOG_PAGE_VAL2", "RX_LOG_PAGE_RELO1",
+ "RX_LOG_PAGE_RELO2", "RX_LOG_PAGE_HDL", "RDC_RED_PARA", "RED_DIS_CNT"
+};
+
+
+/*
+ * Dump the MEM_ADD register first so all the data registers
+ * will have valid data buffer pointers.
+ */
+uint64_t rx_fzc_offset[] = {
+ RX_DMA_CK_DIV_REG, DEF_PT0_RDC_REG, DEF_PT1_RDC_REG, DEF_PT2_RDC_REG,
+ DEF_PT3_RDC_REG, RX_ADDR_MD_REG, PT_DRR_WT0_REG, PT_DRR_WT1_REG,
+ PT_DRR_WT2_REG, PT_DRR_WT3_REG, PT_USE0_REG, PT_USE1_REG,
+ PT_USE2_REG, PT_USE3_REG, RED_RAN_INIT_REG, RX_ADDR_MD_REG,
+ RDMC_PRE_PAR_ERR_REG, RDMC_SHA_PAR_ERR_REG,
+ RDMC_MEM_DATA4_REG, RDMC_MEM_DATA3_REG, RDMC_MEM_DATA2_REG,
+ RDMC_MEM_DATA1_REG, RDMC_MEM_DATA0_REG,
+ RDMC_MEM_ADDR_REG,
+ RX_CTL_DAT_FIFO_STAT_REG, RX_CTL_DAT_FIFO_MASK_REG,
+ RX_CTL_DAT_FIFO_STAT_DBG_REG,
+ RDMC_TRAINING_VECTOR_REG,
+};
+
+
+const char *rx_fzc_name[] = {
+ "RX_DMA_CK_DIV", "DEF_PT0_RDC", "DEF_PT1_RDC", "DEF_PT2_RDC",
+ "DEF_PT3_RDC", "RX_ADDR_MD", "PT_DRR_WT0", "PT_DRR_WT1",
+ "PT_DRR_WT2", "PT_DRR_WT3", "PT_USE0", "PT_USE1",
+ "PT_USE2", "PT_USE3", "RED_RAN_INIT", "RX_ADDR_MD",
+ "RDMC_PRE_PAR_ERR", "RDMC_SHA_PAR_ERR",
+ "RDMC_MEM_DATA4", "RDMC_MEM_DATA3", "RDMC_MEM_DATA2",
+ "RDMC_MEM_DATA1", "RDMC_MEM_DATA0",
+ "RDMC_MEM_ADDR",
+ "RX_CTL_DAT_FIFO_STAT", "RX_CTL_DAT_FIFO_MASK",
+ "RDMC_TRAINING_VECTOR_REG",
+ "RX_CTL_DAT_FIFO_STAT_DBG_REG"
+};
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op);
+npi_status_t
+npi_rxdma_cfg_rdc_rcr_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op,
+ uint16_t param);
+
+
+/*
+ * npi_rxdma_dump_rdc_regs
+ * Dumps the contents of rdc csrs and fzc registers
+ *
+ * Input:
+ * rdc: RX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t
+npi_rxdma_dump_rdc_regs(npi_handle_t handle, uint8_t rdc)
+{
+
+ uint64_t value, offset;
+ int num_regs, i;
+#ifdef NPI_DEBUG
+ extern uint64_t npi_debug_level;
+ uint64_t old_npi_debug_level = npi_debug_level;
+#endif
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_dump_rdc_regs"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+#ifdef NPI_DEBUG
+ npi_debug_level |= DUMP_ALWAYS;
+#endif
+ num_regs = sizeof (rdc_dmc_offset) / sizeof (uint64_t);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nDMC Register Dump for Channel %d\n",
+ rdc));
+ for (i = 0; i < num_regs; i++) {
+ RXDMA_REG_READ64(handle, rdc_dmc_offset[i], rdc, &value);
+ offset = NXGE_RXDMA_OFFSET(rdc_dmc_offset[i], handle.is_vraddr,
+ rdc);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "%08llx %s\t %08llx \n",
+ offset, rdc_dmc_name[i], value));
+ }
+
+ NPI_DEBUG_MSG((handle.function, DUMP_ALWAYS,
+ "\nFZC_DMC Register Dump for Channel %d\n",
+ rdc));
+ num_regs = sizeof (rdc_fzc_offset) / sizeof (uint64_t);
+
+ for (i = 0; i < num_regs; i++) {
+ offset = REG_FZC_RDC_OFFSET(rdc_fzc_offset[i], rdc);
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "%8llx %s\t %8llx \n",
+ rdc_fzc_offset[i], rdc_fzc_name[i],
+ value));
+
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n Register Dump for Channel %d done\n",
+ rdc));
+#ifdef NPI_DEBUG
+ npi_debug_level = old_npi_debug_level;
+#endif
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_rxdma_dump_fzc_regs
+ * Dumps the contents of rdc csrs and fzc registers
+ *
+ * Input:
+ * rdc: RX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+npi_status_t
+npi_rxdma_dump_fzc_regs(npi_handle_t handle)
+{
+
+ uint64_t value;
+ int num_regs, i;
+
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nFZC_DMC Common Register Dump\n"));
+ num_regs = sizeof (rx_fzc_offset) / sizeof (uint64_t);
+
+ for (i = 0; i < num_regs; i++) {
+ NXGE_REG_RD64(handle, rx_fzc_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "0x%08llx %s\t 0x%08llx \n",
+ rx_fzc_offset[i],
+ rx_fzc_name[i], value));
+ }
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FZC_DMC Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/* per rdc config functions */
+
+npi_status_t
+npi_rxdma_cfg_logical_page_disable(npi_handle_t handle, uint8_t rdc,
+ uint8_t page_num)
+{
+ log_page_vld_t page_vld;
+ uint64_t valid_offset;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_logical_page_disable"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ if (!RXDMA_PAGE_VALID(page_num)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_logical_page_disable"
+ " Illegal page number %d \n",
+ page_num));
+ return (NPI_RXDMA_PAGE_INVALID);
+ }
+
+ valid_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VLD_REG, rdc);
+ NXGE_REG_RD64(handle, valid_offset, &page_vld.value);
+
+ if (page_num == 0)
+ page_vld.bits.ldw.page0 = 0;
+
+ if (page_num == 1)
+ page_vld.bits.ldw.page1 = 0;
+
+ NXGE_REG_WR64(handle, valid_offset, page_vld.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+npi_status_t
+npi_rxdma_cfg_logical_page(npi_handle_t handle, uint8_t rdc,
+ dma_log_page_t *pg_cfg)
+{
+ log_page_vld_t page_vld;
+ log_page_mask_t page_mask;
+ log_page_value_t page_value;
+ log_page_relo_t page_reloc;
+ uint64_t value_offset, reloc_offset, mask_offset;
+ uint64_t valid_offset;
+
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_logical_page"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ if (!RXDMA_PAGE_VALID(pg_cfg->page_num)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_logical_page"
+ " Illegal page number %d \n",
+ pg_cfg->page_num));
+ return (NPI_RXDMA_PAGE_INVALID);
+ }
+
+ valid_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VLD_REG, rdc);
+ NXGE_REG_RD64(handle, valid_offset, &page_vld.value);
+
+ if (pg_cfg->valid == 0) {
+ if (pg_cfg->page_num == 0)
+ page_vld.bits.ldw.page0 = 0;
+
+ if (pg_cfg->page_num == 1)
+ page_vld.bits.ldw.page1 = 0;
+ NXGE_REG_WR64(handle, valid_offset, page_vld.value);
+ return (NPI_SUCCESS);
+ }
+
+ if (pg_cfg->page_num == 0) {
+ mask_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_MASK1_REG, rdc);
+ value_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VAL1_REG, rdc);
+ reloc_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_RELO1_REG, rdc);
+ page_vld.bits.ldw.page0 = 1;
+ }
+
+ if (pg_cfg->page_num == 1) {
+ mask_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_MASK2_REG, rdc);
+ value_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VAL2_REG, rdc);
+ reloc_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_RELO2_REG, rdc);
+ page_vld.bits.ldw.page1 = 1;
+ }
+
+
+ page_vld.bits.ldw.func = pg_cfg->func_num;
+
+ page_mask.value = 0;
+ page_value.value = 0;
+ page_reloc.value = 0;
+
+
+ page_mask.bits.ldw.mask = pg_cfg->mask >> LOG_PAGE_ADDR_SHIFT;
+ page_value.bits.ldw.value = pg_cfg->value >> LOG_PAGE_ADDR_SHIFT;
+ page_reloc.bits.ldw.relo = pg_cfg->reloc >> LOG_PAGE_ADDR_SHIFT;
+
+
+ NXGE_REG_WR64(handle, mask_offset, page_mask.value);
+ NXGE_REG_WR64(handle, value_offset, page_value.value);
+ NXGE_REG_WR64(handle, reloc_offset, page_reloc.value);
+
+
+/* enable the logical page */
+ NXGE_REG_WR64(handle, valid_offset, page_vld.value);
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_rxdma_cfg_logical_page_handle(npi_handle_t handle, uint8_t rdc,
+ uint64_t page_handle)
+{
+ uint64_t offset;
+ log_page_hdl_t page_hdl;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_logical_page_handle"
+ " Illegal RDC number %d \n", rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+
+ page_hdl.value = 0;
+
+ page_hdl.bits.ldw.handle = (uint32_t)page_handle;
+ offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_HDL_REG, rdc);
+ NXGE_REG_WR64(handle, offset, page_hdl.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/* RX DMA functions */
+
+npi_status_t
+npi_rxdma_cfg_rdc_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op)
+{
+
+ rxdma_cfig1_t cfg;
+ uint32_t count = RXDMA_RESET_TRY_COUNT;
+ uint32_t delay_time = RXDMA_RESET_DELAY;
+ uint32_t error = NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RESET_ERR, rdc);
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_cfg_rdc_ctl"
+ " Illegal RDC number %d \n", rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+
+ switch (op) {
+ case RXDMA_OP_ENABLE:
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ cfg.bits.ldw.en = 1;
+ RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG,
+ rdc, cfg.value);
+
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ while ((count--) && (cfg.bits.ldw.qst == 0)) {
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ }
+
+ if (cfg.bits.ldw.qst == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_cfg_rdc_ctl"
+ " RXDMA_OP_ENABLE Failed for RDC %d \n",
+ rdc));
+ return (error);
+ }
+
+ break;
+ case RXDMA_OP_DISABLE:
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ cfg.bits.ldw.en = 0;
+ RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG,
+ rdc, cfg.value);
+
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ while ((count--) && (cfg.bits.ldw.qst == 0)) {
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ }
+ if (cfg.bits.ldw.qst == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_cfg_rdc_ctl"
+ " RXDMA_OP_DISABLE Failed for RDC %d \n",
+ rdc));
+ return (error);
+ }
+
+ break;
+ case RXDMA_OP_RESET:
+ cfg.value = 0;
+ cfg.bits.ldw.rst = 1;
+ RXDMA_REG_WRITE64(handle,
+ RXDMA_CFIG1_REG,
+ rdc, cfg.value);
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ while ((count--) && (cfg.bits.ldw.rst)) {
+ NXGE_DELAY(delay_time);
+ RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc,
+ &cfg.value);
+ }
+ if (count == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_cfg_rdc_ctl"
+ " Reset Failed for RDC %d \n",
+ rdc));
+ return (error);
+ }
+ break;
+ default:
+ return (NPI_RXDMA_SW_PARAM_ERROR);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_enable(npi_handle_t handle, uint8_t rdc)
+{
+ return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_ENABLE));
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_disable(npi_handle_t handle, uint8_t rdc)
+{
+ return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_DISABLE));
+}
+
+npi_status_t
+npi_rxdma_cfg_rdc_reset(npi_handle_t handle, uint8_t rdc)
+{
+ return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_RESET));
+}
+
+
+
+
+
+/*
+ * npi_rxdma_cfg_defualt_port_rdc()
+ * Set the default rdc for the port
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * portnm: Physical Port Number
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ * NPI_RXDMA_PORT_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_default_port_rdc(npi_handle_t handle,
+ uint8_t portnm, uint8_t rdc)
+{
+
+ uint64_t offset;
+ def_pt_rdc_t cfg;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_default_port_rdc"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ if (!RXDMA_PORT_VALID(portnm)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_default_port_rdc"
+ " Illegal Port number %d \n",
+ portnm));
+ return (NPI_RXDMA_PORT_INVALID);
+ }
+
+ offset = DEF_PT_RDC_REG(portnm);
+ cfg.value = 0;
+ cfg.bits.ldw.rdc = rdc;
+ NXGE_REG_WR64(handle, offset, cfg.value);
+ return (NPI_SUCCESS);
+}
+
+
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_rcr_ctl(npi_handle_t handle, uint8_t rdc,
+ uint8_t op, uint16_t param)
+{
+ rcrcfig_b_t rcr_cfgb;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_rdc_rcr_ctl"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+
+ RXDMA_REG_READ64(handle, RCRCFIG_B_REG, rdc, &rcr_cfgb.value);
+
+ switch (op) {
+ case RCR_TIMEOUT_ENABLE:
+ rcr_cfgb.bits.ldw.timeout = (uint8_t)param;
+ rcr_cfgb.bits.ldw.entout = 1;
+ break;
+
+ case RCR_THRESHOLD:
+ rcr_cfgb.bits.ldw.pthres = param;
+ break;
+
+ case RCR_TIMEOUT_DISABLE:
+ rcr_cfgb.bits.ldw.entout = 0;
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_rdc_rcr_ctl"
+ " Illegal opcode %x \n",
+ op));
+ return (NPI_RXDMA_OPCODE_INVALID(rdc));
+ }
+
+ RXDMA_REG_WRITE64(handle, RCRCFIG_B_REG, rdc, rcr_cfgb.value);
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_rcr_timeout_disable(npi_handle_t handle, uint8_t rdc)
+{
+ return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc,
+ RCR_TIMEOUT_DISABLE, 0));
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_rdc_rcr_threshold(npi_handle_t handle, uint8_t rdc,
+ uint16_t rcr_threshold)
+{
+ return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc,
+ RCR_THRESHOLD, rcr_threshold));
+
+}
+
+npi_status_t
+npi_rxdma_cfg_rdc_rcr_timeout(npi_handle_t handle, uint8_t rdc,
+ uint8_t rcr_timeout)
+{
+ return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc,
+ RCR_TIMEOUT_ENABLE, rcr_timeout));
+
+}
+
+
+
+/*
+ * npi_rxdma_cfg_rdc_ring()
+ * Configure The RDC channel Rcv Buffer Ring
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rdc_params: RDC confiuration parameters
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t
+npi_rxdma_cfg_rdc_ring(npi_handle_t handle, uint8_t rdc,
+ rdc_desc_cfg_t *rdc_desc_cfg)
+{
+ rbr_cfig_a_t cfga;
+ rbr_cfig_b_t cfgb;
+ rxdma_cfig1_t cfg1;
+ rxdma_cfig2_t cfg2;
+ rcrcfig_a_t rcr_cfga;
+ rcrcfig_b_t rcr_cfgb;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_rdc_ring"
+ " Illegal RDC number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+
+ cfga.value = 0;
+ cfgb.value = 0;
+ cfg1.value = 0;
+ cfg2.value = 0;
+
+ if (rdc_desc_cfg->mbox_enable == 1) {
+ cfg1.bits.ldw.mbaddr_h =
+ (rdc_desc_cfg->mbox_addr >> 32) & 0xfff;
+ cfg2.bits.ldw.mbaddr =
+ ((rdc_desc_cfg->mbox_addr &
+ RXDMA_CFIG2_MBADDR_L_MASK) >>
+ RXDMA_CFIG2_MBADDR_L_SHIFT);
+
+
+ /*
+ * Only after all the configurations are set, then
+ * enable the RDC or else configuration fatal error
+ * will be returned (especially if the Hypervisor
+ * set up the logical pages with non-zero values.
+ * This NPI function only sets up the configuration.
+ * Call the enable function to enable the RDMC!
+ */
+ }
+
+
+ if (rdc_desc_cfg->full_hdr == 1)
+ cfg2.bits.ldw.full_hdr = 1;
+
+ if (RXDMA_BUFF_OFFSET_VALID(rdc_desc_cfg->offset)) {
+ cfg2.bits.ldw.offset = rdc_desc_cfg->offset;
+ } else {
+ cfg2.bits.ldw.offset = SW_OFFSET_NO_OFFSET;
+ }
+
+ /* rbr config */
+
+ cfga.value = (rdc_desc_cfg->rbr_addr & (RBR_CFIG_A_STDADDR_MASK |
+ RBR_CFIG_A_STDADDR_BASE_MASK));
+
+ if ((rdc_desc_cfg->rbr_len < RBR_DEFAULT_MIN_LEN) ||
+ (rdc_desc_cfg->rbr_len > RBR_DEFAULT_MAX_LEN)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_cfg_rdc_ring"
+ " Illegal RBR Queue Length %d \n",
+ rdc_desc_cfg->rbr_len));
+ return (NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RBRSZIE_INVALID, rdc));
+ }
+
+
+ cfga.bits.hdw.len = rdc_desc_cfg->rbr_len;
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ "npi_rxdma_cfg_rdc_ring"
+ " CFGA 0x%llx hdw.len %d (RBR LEN %d)\n",
+ cfga.value, cfga.bits.hdw.len,
+ rdc_desc_cfg->rbr_len));
+
+ if (rdc_desc_cfg->page_size == SIZE_4KB)
+ cfgb.bits.ldw.bksize = RBR_BKSIZE_4K;
+ else if (rdc_desc_cfg->page_size == SIZE_8KB)
+ cfgb.bits.ldw.bksize = RBR_BKSIZE_8K;
+ else if (rdc_desc_cfg->page_size == SIZE_16KB)
+ cfgb.bits.ldw.bksize = RBR_BKSIZE_16K;
+ else if (rdc_desc_cfg->page_size == SIZE_32KB)
+ cfgb.bits.ldw.bksize = RBR_BKSIZE_32K;
+ else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "rxdma_cfg_rdc_ring"
+ " blksize: Illegal buffer size %d \n",
+ rdc_desc_cfg->page_size));
+ return (NPI_RXDMA_BUFSZIE_INVALID);
+ }
+
+ if (rdc_desc_cfg->valid0) {
+
+ if (rdc_desc_cfg->size0 == SIZE_256B)
+ cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_256B;
+ else if (rdc_desc_cfg->size0 == SIZE_512B)
+ cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_512B;
+ else if (rdc_desc_cfg->size0 == SIZE_1KB)
+ cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_1K;
+ else if (rdc_desc_cfg->size0 == SIZE_2KB)
+ cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_2K;
+ else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " blksize0: Illegal buffer size %x \n",
+ rdc_desc_cfg->size0));
+ return (NPI_RXDMA_BUFSZIE_INVALID);
+ }
+ cfgb.bits.ldw.vld0 = 1;
+ } else {
+ cfgb.bits.ldw.vld0 = 0;
+ }
+
+
+ if (rdc_desc_cfg->valid1) {
+ if (rdc_desc_cfg->size1 == SIZE_1KB)
+ cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_1K;
+ else if (rdc_desc_cfg->size1 == SIZE_2KB)
+ cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_2K;
+ else if (rdc_desc_cfg->size1 == SIZE_4KB)
+ cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_4K;
+ else if (rdc_desc_cfg->size1 == SIZE_8KB)
+ cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_8K;
+ else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " blksize1: Illegal buffer size %x \n",
+ rdc_desc_cfg->size1));
+ return (NPI_RXDMA_BUFSZIE_INVALID);
+ }
+ cfgb.bits.ldw.vld1 = 1;
+ } else {
+ cfgb.bits.ldw.vld1 = 0;
+ }
+
+
+ if (rdc_desc_cfg->valid2) {
+ if (rdc_desc_cfg->size2 == SIZE_2KB)
+ cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_2K;
+ else if (rdc_desc_cfg->size2 == SIZE_4KB)
+ cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_4K;
+ else if (rdc_desc_cfg->size2 == SIZE_8KB)
+ cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_8K;
+ else if (rdc_desc_cfg->size2 == SIZE_16KB)
+ cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_16K;
+ else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " blksize2: Illegal buffer size %x \n",
+ rdc_desc_cfg->size2));
+ return (NPI_RXDMA_BUFSZIE_INVALID);
+ }
+ cfgb.bits.ldw.vld2 = 1;
+ } else {
+ cfgb.bits.ldw.vld2 = 0;
+ }
+
+
+ rcr_cfga.value = (rdc_desc_cfg->rcr_addr &
+ (RCRCFIG_A_STADDR_MASK |
+ RCRCFIG_A_STADDR_BASE_MASK));
+
+
+ if ((rdc_desc_cfg->rcr_len < RCR_DEFAULT_MIN_LEN) ||
+ (rdc_desc_cfg->rcr_len > NXGE_RCR_MAX)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " Illegal RCR Queue Length %d \n",
+ rdc_desc_cfg->rcr_len));
+ return (NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RCRSZIE_INVALID, rdc));
+ }
+
+ rcr_cfga.bits.hdw.len = rdc_desc_cfg->rcr_len;
+
+
+ rcr_cfgb.value = 0;
+ if (rdc_desc_cfg->rcr_timeout_enable == 1) {
+ /* check if the rcr timeout value is valid */
+
+ if (RXDMA_RCR_TO_VALID(rdc_desc_cfg->rcr_timeout)) {
+ rcr_cfgb.bits.ldw.timeout = rdc_desc_cfg->rcr_timeout;
+ rcr_cfgb.bits.ldw.entout = 1;
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " Illegal RCR Timeout value %d \n",
+ rdc_desc_cfg->rcr_timeout));
+ rcr_cfgb.bits.ldw.entout = 0;
+ }
+ } else {
+ rcr_cfgb.bits.ldw.entout = 0;
+ }
+
+ /* check if the rcr threshold value is valid */
+ if (RXDMA_RCR_THRESH_VALID(rdc_desc_cfg->rcr_threshold)) {
+ rcr_cfgb.bits.ldw.pthres = rdc_desc_cfg->rcr_threshold;
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_rdc_ring"
+ " Illegal RCR Threshold value %d \n",
+ rdc_desc_cfg->rcr_threshold));
+ rcr_cfgb.bits.ldw.pthres = 1;
+ }
+
+ /* now do the actual HW configuration */
+ RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG, rdc, cfg1.value);
+ RXDMA_REG_WRITE64(handle, RXDMA_CFIG2_REG, rdc, cfg2.value);
+
+
+ RXDMA_REG_WRITE64(handle, RBR_CFIG_A_REG, rdc, cfga.value);
+ RXDMA_REG_WRITE64(handle, RBR_CFIG_B_REG, rdc, cfgb.value);
+
+ RXDMA_REG_WRITE64(handle, RCRCFIG_A_REG, rdc, rcr_cfga.value);
+ RXDMA_REG_WRITE64(handle, RCRCFIG_B_REG, rdc, rcr_cfgb.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+/*
+ * npi_rxdma_red_discard_stat_get
+ * Gets the current discrad count due RED
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rx_disc_cnt_t Structure to write current RDC discard stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t
+npi_rxdma_red_discard_stat_get(npi_handle_t handle, uint8_t rdc,
+ rx_disc_cnt_t *cnt)
+{
+ uint64_t offset;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_red_discard_stat_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ offset = RDC_RED_RDC_DISC_REG(rdc);
+ NXGE_REG_RD64(handle, offset, &cnt->value);
+ if (cnt->bits.ldw.oflow) {
+ NPI_DEBUG_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_red_discard_stat_get"
+ " Counter overflow for channel %d ",
+ " ..... clearing \n",
+ rdc));
+ cnt->bits.ldw.oflow = 0;
+ NXGE_REG_WR64(handle, offset, cnt->value);
+ cnt->bits.ldw.oflow = 1;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_rxdma_red_discard_oflow_clear
+ * Clear RED discard counter overflow bit
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t
+npi_rxdma_red_discard_oflow_clear(npi_handle_t handle, uint8_t rdc)
+
+{
+ uint64_t offset;
+ rx_disc_cnt_t cnt;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_red_discard_oflow_clear"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ offset = RDC_RED_RDC_DISC_REG(rdc);
+ NXGE_REG_RD64(handle, offset, &cnt.value);
+ if (cnt.bits.ldw.oflow) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_red_discard_oflow_clear"
+ " Counter overflow for channel %d ",
+ " ..... clearing \n",
+ rdc));
+ cnt.bits.ldw.oflow = 0;
+ NXGE_REG_WR64(handle, offset, cnt.value);
+ }
+ return (NPI_SUCCESS);
+}
+
+
+
+
+/*
+ * npi_rxdma_misc_discard_stat_get
+ * Gets the current discrad count for the rdc due to
+ * buffer pool empty
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rx_disc_cnt_t Structure to write current RDC discard stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+
+npi_status_t
+npi_rxdma_misc_discard_stat_get(npi_handle_t handle, uint8_t rdc,
+ rx_disc_cnt_t *cnt)
+{
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_misc_discard_stat_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ RXDMA_REG_READ64(handle, RXMISC_DISCARD_REG, rdc, &cnt->value);
+ if (cnt->bits.ldw.oflow) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_misc_discard_stat_get"
+ " Counter overflow for channel %d ",
+ " ..... clearing \n",
+ rdc));
+ cnt->bits.ldw.oflow = 0;
+ RXDMA_REG_WRITE64(handle, RXMISC_DISCARD_REG, rdc, cnt->value);
+ cnt->bits.ldw.oflow = 1;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_rxdma_red_discard_oflow_clear
+ * Clear RED discard counter overflow bit
+ * clear the overflow bit for buffer pool empty discrad counter
+ * for the rdc
+ *
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t
+npi_rxdma_misc_discard_oflow_clear(npi_handle_t handle, uint8_t rdc)
+{
+ rx_disc_cnt_t cnt;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_misc_discard_oflow_clear"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ RXDMA_REG_READ64(handle, RXMISC_DISCARD_REG, rdc, &cnt.value);
+ if (cnt.bits.ldw.oflow) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_misc_discard_oflow_clear"
+ " Counter overflow for channel %d ",
+ " ..... clearing \n",
+ rdc));
+ cnt.bits.ldw.oflow = 0;
+ RXDMA_REG_WRITE64(handle, RXMISC_DISCARD_REG, rdc, cnt.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_rxdma_ring_perr_stat_get
+ * Gets the current RDC Memory parity error
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * pre_log: Structure to write current RDC Prefetch memory
+ * Parity Error stat
+ * sha_log: Structure to write current RDC Shadow memory
+ * Parity Error stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ *
+ */
+
+npi_status_t
+npi_rxdma_ring_perr_stat_get(npi_handle_t handle,
+ rdmc_par_err_log_t *pre_log,
+ rdmc_par_err_log_t *sha_log)
+{
+ uint64_t pre_offset, sha_offset;
+ rdmc_par_err_log_t clr;
+ int clr_bits = 0;
+
+ pre_offset = RDMC_PRE_PAR_ERR_REG;
+ sha_offset = RDMC_SHA_PAR_ERR_REG;
+ NXGE_REG_RD64(handle, pre_offset, &pre_log->value);
+ NXGE_REG_RD64(handle, sha_offset, &sha_log->value);
+
+ clr.value = pre_log->value;
+ if (pre_log->bits.ldw.err) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " PRE ERR Bit set ..... clearing \n"));
+ clr.bits.ldw.err = 0;
+ clr_bits++;
+ }
+
+ if (pre_log->bits.ldw.merr) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " PRE MERR Bit set ..... clearing \n"));
+ clr.bits.ldw.merr = 0;
+ clr_bits++;
+ }
+
+ if (clr_bits) {
+ NXGE_REG_WR64(handle, pre_offset, clr.value);
+ }
+
+ clr_bits = 0;
+ clr.value = sha_log->value;
+ if (sha_log->bits.ldw.err) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " SHA ERR Bit set ..... clearing \n"));
+ clr.bits.ldw.err = 0;
+ clr_bits++;
+ }
+
+ if (sha_log->bits.ldw.merr) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " SHA MERR Bit set ..... clearing \n"));
+ clr.bits.ldw.merr = 0;
+ clr_bits++;
+ }
+
+ if (clr_bits) {
+ NXGE_REG_WR64(handle, sha_offset, clr.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_rxdma_ring_perr_stat_clear
+ * Clear RDC Memory Parity Error counter overflow bits
+ *
+ * Inputs:
+ * Return:
+ * NPI_SUCCESS
+ *
+ */
+
+npi_status_t
+npi_rxdma_ring_perr_stat_clear(npi_handle_t handle)
+{
+ uint64_t pre_offset, sha_offset;
+ rdmc_par_err_log_t clr;
+ int clr_bits = 0;
+ pre_offset = RDMC_PRE_PAR_ERR_REG;
+ sha_offset = RDMC_SHA_PAR_ERR_REG;
+
+ NXGE_REG_RD64(handle, pre_offset, &clr.value);
+
+ if (clr.bits.ldw.err) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " PRE ERR Bit set ..... clearing \n"));
+ clr.bits.ldw.err = 0;
+ clr_bits++;
+ }
+
+ if (clr.bits.ldw.merr) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " PRE MERR Bit set ..... clearing \n"));
+ clr.bits.ldw.merr = 0;
+ clr_bits++;
+ }
+
+ if (clr_bits) {
+ NXGE_REG_WR64(handle, pre_offset, clr.value);
+ }
+
+ clr_bits = 0;
+ NXGE_REG_RD64(handle, sha_offset, &clr.value);
+ if (clr.bits.ldw.err) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " SHA ERR Bit set ..... clearing \n"));
+ clr.bits.ldw.err = 0;
+ clr_bits++;
+ }
+
+ if (clr.bits.ldw.merr) {
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_ring_perr_stat_get"
+ " SHA MERR Bit set ..... clearing \n"));
+ clr.bits.ldw.merr = 0;
+ clr_bits++;
+ }
+
+ if (clr_bits) {
+ NXGE_REG_WR64(handle, sha_offset, clr.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+/* Access the RDMC Memory: used for debugging */
+npi_status_t
+npi_rxdma_rdmc_memory_io(npi_handle_t handle,
+ rdmc_mem_access_t *data, uint8_t op)
+{
+ uint64_t d0_offset, d1_offset, d2_offset, d3_offset, d4_offset;
+ uint64_t addr_offset;
+ rdmc_mem_addr_t addr;
+ rdmc_mem_data_t d0, d1, d2, d3, d4;
+ d0.value = 0;
+ d1.value = 0;
+ d2.value = 0;
+ d3.value = 0;
+ d4.value = 0;
+ addr.value = 0;
+
+
+ if ((data->location != RDMC_MEM_ADDR_PREFETCH) &&
+ (data->location != RDMC_MEM_ADDR_SHADOW)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdmc_memory_io"
+ " Illegal memory Type %x \n",
+ data->location));
+ return (NPI_RXDMA_OPCODE_INVALID(0));
+ }
+
+ addr_offset = RDMC_MEM_ADDR_REG;
+ addr.bits.ldw.addr = data->addr;
+ addr.bits.ldw.pre_shad = data->location;
+
+ d0_offset = RDMC_MEM_DATA0_REG;
+ d1_offset = RDMC_MEM_DATA1_REG;
+ d2_offset = RDMC_MEM_DATA2_REG;
+ d3_offset = RDMC_MEM_DATA3_REG;
+ d4_offset = RDMC_MEM_DATA4_REG;
+
+
+ if (op == RDMC_MEM_WRITE) {
+ d0.bits.ldw.data = data->data[0];
+ d1.bits.ldw.data = data->data[1];
+ d2.bits.ldw.data = data->data[2];
+ d3.bits.ldw.data = data->data[3];
+ d4.bits.ldw.data = data->data[4];
+ NXGE_REG_WR64(handle, addr_offset, addr.value);
+ NXGE_REG_WR64(handle, d0_offset, d0.value);
+ NXGE_REG_WR64(handle, d1_offset, d1.value);
+ NXGE_REG_WR64(handle, d2_offset, d2.value);
+ NXGE_REG_WR64(handle, d3_offset, d3.value);
+ NXGE_REG_WR64(handle, d4_offset, d4.value);
+ }
+
+ if (op == RDMC_MEM_READ) {
+ NXGE_REG_WR64(handle, addr_offset, addr.value);
+ NXGE_REG_RD64(handle, d4_offset, &d4.value);
+ NXGE_REG_RD64(handle, d3_offset, &d3.value);
+ NXGE_REG_RD64(handle, d2_offset, &d2.value);
+ NXGE_REG_RD64(handle, d1_offset, &d1.value);
+ NXGE_REG_RD64(handle, d0_offset, &d0.value);
+
+ data->data[0] = d0.bits.ldw.data;
+ data->data[1] = d1.bits.ldw.data;
+ data->data[2] = d2.bits.ldw.data;
+ data->data[3] = d3.bits.ldw.data;
+ data->data[4] = d4.bits.ldw.data;
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdmc_memory_io"
+ " Illegal opcode %x \n",
+ op));
+ return (NPI_RXDMA_OPCODE_INVALID(0));
+
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/* system wide conf functions */
+
+npi_status_t
+npi_rxdma_cfg_clock_div_set(npi_handle_t handle, uint16_t count)
+{
+ uint64_t offset;
+ rx_dma_ck_div_t clk_div;
+
+ offset = RX_DMA_CK_DIV_REG;
+
+ clk_div.value = 0;
+ clk_div.bits.ldw.cnt = count;
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_cfg_clock_div_set: add 0x%llx "
+ "handle 0x%llx value 0x%llx",
+ handle.regp, handle.regh, clk_div.value));
+
+ NXGE_REG_WR64(handle, offset, clk_div.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+
+npi_status_t
+npi_rxdma_cfg_red_rand_init(npi_handle_t handle, uint16_t init_value)
+{
+ uint64_t offset;
+ red_ran_init_t rand_reg;
+
+ offset = RED_RAN_INIT_REG;
+
+ rand_reg.value = 0;
+ rand_reg.bits.ldw.init = init_value;
+ rand_reg.bits.ldw.enable = 1;
+ NXGE_REG_WR64(handle, offset, rand_reg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+npi_status_t
+npi_rxdma_cfg_red_rand_disable(npi_handle_t handle)
+{
+ uint64_t offset;
+ red_ran_init_t rand_reg;
+
+ offset = RED_RAN_INIT_REG;
+
+ NXGE_REG_RD64(handle, offset, &rand_reg.value);
+ rand_reg.bits.ldw.enable = 0;
+ NXGE_REG_WR64(handle, offset, rand_reg.value);
+
+ return (NPI_SUCCESS);
+
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_32bitmode_enable(npi_handle_t handle)
+{
+ uint64_t offset;
+ rx_addr_md_t md_reg;
+ offset = RX_ADDR_MD_REG;
+ md_reg.value = 0;
+ md_reg.bits.ldw.mode32 = 1;
+
+ NXGE_REG_WR64(handle, offset, md_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_32bitmode_disable(npi_handle_t handle)
+{
+ uint64_t offset;
+ rx_addr_md_t md_reg;
+ offset = RX_ADDR_MD_REG;
+ md_reg.value = 0;
+
+ NXGE_REG_WR64(handle, offset, md_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+npi_status_t
+npi_rxdma_cfg_ram_access_enable(npi_handle_t handle)
+{
+ uint64_t offset;
+ rx_addr_md_t md_reg;
+ offset = RX_ADDR_MD_REG;
+ NXGE_REG_RD64(handle, offset, &md_reg.value);
+ md_reg.bits.ldw.ram_acc = 1;
+ NXGE_REG_WR64(handle, offset, md_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+npi_status_t
+npi_rxdma_cfg_ram_access_disable(npi_handle_t handle)
+{
+ uint64_t offset;
+ rx_addr_md_t md_reg;
+ offset = RX_ADDR_MD_REG;
+ NXGE_REG_RD64(handle, offset, &md_reg.value);
+ md_reg.bits.ldw.ram_acc = 0;
+ NXGE_REG_WR64(handle, offset, md_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+
+
+#define WEIGHT_FACTOR 3/2
+/* assume weight is in byte frames unit */
+
+npi_status_t npi_rxdma_cfg_port_ddr_weight(npi_handle_t handle,
+ uint8_t portnm, uint32_t weight)
+{
+
+ pt_drr_wt_t wt_reg;
+ uint64_t offset;
+ if (!RXDMA_PORT_VALID(portnm)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_port_ddr_weight"
+ " Illegal Port Number %d \n",
+ portnm));
+ return (NPI_RXDMA_PORT_INVALID);
+ }
+
+ offset = PT_DRR_WT_REG(portnm);
+ wt_reg.value = 0;
+ wt_reg.bits.ldw.wt = weight;
+ NXGE_REG_WR64(handle, offset, wt_reg.value);
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t npi_rxdma_port_usage_get(npi_handle_t handle,
+ uint8_t portnm, uint32_t *blocks)
+{
+
+ pt_use_t use_reg;
+ uint64_t offset;
+
+ if (!RXDMA_PORT_VALID(portnm)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_port_usage_get"
+ " Illegal Port Number %d \n",
+ portnm));
+ return (NPI_RXDMA_PORT_INVALID);
+ }
+
+ offset = PT_USE_REG(portnm);
+ NXGE_REG_RD64(handle, offset, &use_reg.value);
+ *blocks = use_reg.bits.ldw.cnt;
+ return (NPI_SUCCESS);
+
+}
+
+
+
+npi_status_t npi_rxdma_cfg_wred_param(npi_handle_t handle, uint8_t rdc,
+ rdc_red_para_t *wred_params)
+{
+ rdc_red_para_t wred_reg;
+ uint64_t offset;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_cfg_wred_param"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ /*
+ * need to update RDC_RED_PARA_REG as well as bit defs in
+ * the hw header file
+ */
+ offset = RDC_RED_RDC_PARA_REG(rdc);
+
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_cfg_wred_param: "
+ "set RED_PARA: passed value 0x%llx "
+ "win 0x%x thre 0x%x sync 0x%x thre_sync 0x%x",
+ wred_params->value,
+ wred_params->bits.ldw.win,
+ wred_params->bits.ldw.thre,
+ wred_params->bits.ldw.win_syn,
+ wred_params->bits.ldw.thre_sync));
+
+ wred_reg.value = 0;
+ wred_reg.bits.ldw.win = wred_params->bits.ldw.win;
+ wred_reg.bits.ldw.thre = wred_params->bits.ldw.thre;
+ wred_reg.bits.ldw.win_syn = wred_params->bits.ldw.win_syn;
+ wred_reg.bits.ldw.thre_sync = wred_params->bits.ldw.thre_sync;
+ NXGE_REG_WR64(handle, offset, wred_reg.value);
+
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ "set RED_PARA: value 0x%llx "
+ "win 0x%x thre 0x%x sync 0x%x thre_sync 0x%x",
+ wred_reg.value,
+ wred_reg.bits.ldw.win,
+ wred_reg.bits.ldw.thre,
+ wred_reg.bits.ldw.win_syn,
+ wred_reg.bits.ldw.thre_sync));
+
+ return (NPI_SUCCESS);
+}
+
+
+
+/*
+ * npi_rxdma_cfg_rdc_table()
+ * Configure/populate the RDC table
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * table: RDC Group Number
+ * rdc[]: Array of RX DMA Channels
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_RXDMA_TABLE_INVALID
+ *
+ */
+
+npi_status_t
+npi_rxdma_cfg_rdc_table(npi_handle_t handle,
+ uint8_t table, uint8_t rdc[])
+{
+ uint64_t offset;
+ int tbl_offset;
+ rdc_tbl_t tbl_reg;
+ tbl_reg.value = 0;
+
+ if (!RXDMA_TABLE_VALID(table)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_cfg_rdc_table"
+ " Illegal RDC Rable Number %d \n",
+ rdc));
+ return (NPI_RXDMA_TABLE_INVALID);
+ }
+
+ offset = REG_RDC_TABLE_OFFSET(table);
+ for (tbl_offset = 0; tbl_offset < NXGE_MAX_RDCS; tbl_offset++) {
+ tbl_reg.bits.ldw.rdc = rdc[tbl_offset];
+ NXGE_REG_WR64(handle, offset, tbl_reg.value);
+ offset += 8;
+ }
+
+ return (NPI_SUCCESS);
+
+}
+
+npi_status_t
+npi_rxdma_cfg_rdc_table_default_rdc(npi_handle_t handle,
+ uint8_t table, uint8_t rdc)
+{
+ uint64_t offset;
+ rdc_tbl_t tbl_reg;
+ tbl_reg.value = 0;
+
+ if (!RXDMA_TABLE_VALID(table)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_cfg_rdc_table"
+ " Illegal RDC table Number %d \n",
+ rdc));
+ return (NPI_RXDMA_TABLE_INVALID);
+ }
+
+ offset = REG_RDC_TABLE_OFFSET(table);
+ tbl_reg.bits.ldw.rdc = rdc;
+ NXGE_REG_WR64(handle, offset, tbl_reg.value);
+ return (NPI_SUCCESS);
+
+}
+
+npi_status_t
+npi_rxdma_dump_rdc_table(npi_handle_t handle,
+ uint8_t table)
+{
+ uint64_t offset;
+ int tbl_offset;
+ uint64_t value;
+
+ if (!RXDMA_TABLE_VALID(table)) {
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ " npi_rxdma_dump_rdc_table"
+ " Illegal RDC Rable Number %d \n",
+ table));
+ return (NPI_RXDMA_TABLE_INVALID);
+ }
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n Register Dump for RDC Table %d \n",
+ table));
+ offset = REG_RDC_TABLE_OFFSET(table);
+ for (tbl_offset = 0; tbl_offset < NXGE_MAX_RDCS; tbl_offset++) {
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ " 0x%08llx 0x%08llx \n",
+ offset, value));
+ offset += 8;
+ }
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n Register Dump for RDC Table %d done\n",
+ table));
+ return (NPI_SUCCESS);
+
+}
+
+
+npi_status_t
+npi_rxdma_rdc_rbr_stat_get(npi_handle_t handle, uint8_t rdc,
+ rbr_stat_t *rbr_stat)
+{
+
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_rdc_rbr_stat_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ RXDMA_REG_READ64(handle, RBR_STAT_REG, rdc, &rbr_stat->value);
+ return (NPI_SUCCESS);
+}
+
+
+
+
+/*
+ * npi_rxdma_rdc_rbr_head_get
+ * Gets the current rbr head pointer.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * hdptr ptr to write the rbr head value
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rbr_head_get(npi_handle_t handle,
+ uint8_t rdc, addr44_t *hdptr)
+{
+ rbr_hdh_t hh_ptr;
+ rbr_hdl_t hl_ptr;
+
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_rdc_rbr_head_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+ hh_ptr.value = 0;
+ hl_ptr.value = 0;
+ RXDMA_REG_READ64(handle, RBR_HDH_REG, rdc, &hh_ptr.value);
+ RXDMA_REG_READ64(handle, RBR_HDL_REG, rdc, &hl_ptr.value);
+ hdptr->bits.ldw = hl_ptr.bits.ldw.head_l << 2;
+ hdptr->bits.hdw = hh_ptr.bits.ldw.head_h;
+ return (NPI_SUCCESS);
+
+}
+
+
+
+
+npi_status_t
+npi_rxdma_rdc_rcr_qlen_get(npi_handle_t handle, uint8_t rdc,
+ uint16_t *rcr_qlen)
+{
+
+ rcrstat_a_t stats;
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_rdc_rcr_qlen_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+
+ RXDMA_REG_READ64(handle, RCRSTAT_A_REG, rdc, &stats.value);
+ *rcr_qlen = stats.bits.ldw.qlen;
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " rxdma_rdc_rcr_qlen_get"
+ " RDC %d qlen %x qlen %x\n",
+ rdc, *rcr_qlen, stats.bits.ldw.qlen));
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_rxdma_rdc_rcr_tail_get(npi_handle_t handle,
+ uint8_t rdc, addr44_t *tail_addr)
+{
+
+ rcrstat_b_t th_ptr;
+ rcrstat_c_t tl_ptr;
+
+ if (!RXDMA_CHANNEL_VALID(rdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " rxdma_rdc_rcr_tail_get"
+ " Illegal RDC Number %d \n",
+ rdc));
+ return (NPI_RXDMA_RDC_INVALID);
+ }
+ th_ptr.value = 0;
+ tl_ptr.value = 0;
+ RXDMA_REG_READ64(handle, RCRSTAT_B_REG, rdc, &th_ptr.value);
+ RXDMA_REG_READ64(handle, RCRSTAT_C_REG, rdc, &tl_ptr.value);
+ tail_addr->bits.ldw = tl_ptr.bits.ldw.tlptr_l << 3;
+ tail_addr->bits.hdw = th_ptr.bits.ldw.tlptr_h;
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " rxdma_rdc_rcr_tail_get"
+ " RDC %d rcr_tail %llx tl %x\n",
+ rdc, tl_ptr.value,
+ tl_ptr.bits.ldw.tlptr_l));
+
+ return (NPI_SUCCESS);
+
+
+}
+
+
+
+
+/*
+ * npi_rxdma_rxctl_fifo_error_intr_set
+ * Configure The RX ctrl fifo error interrupt generation
+ *
+ * Inputs:
+ * mask: rx_ctl_dat_fifo_mask_t specifying the errors
+ * valid fields in rx_ctl_dat_fifo_mask_t structure are:
+ * zcp_eop_err, ipp_eop_err, id_mismatch. If a field is set
+ * to 1, we will enable interrupt generation for the
+ * corresponding error condition. In the hardware, the bit(s)
+ * have to be cleared to enable interrupt.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_rxdma_rxctl_fifo_error_intr_set(npi_handle_t handle,
+ rx_ctl_dat_fifo_mask_t *mask)
+{
+ uint64_t offset;
+ rx_ctl_dat_fifo_mask_t intr_mask;
+ offset = RX_CTL_DAT_FIFO_MASK_REG;
+ NXGE_REG_RD64(handle, offset, &intr_mask.value);
+
+ if (mask->bits.ldw.ipp_eop_err) {
+ intr_mask.bits.ldw.ipp_eop_err = 0;
+ }
+
+ if (mask->bits.ldw.zcp_eop_err) {
+ intr_mask.bits.ldw.zcp_eop_err = 0;
+ }
+
+ if (mask->bits.ldw.id_mismatch) {
+ intr_mask.bits.ldw.id_mismatch = 0;
+ }
+
+ NXGE_REG_WR64(handle, offset, intr_mask.value);
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_rxdma_rxctl_fifo_error_stat_get
+ * Read The RX ctrl fifo error Status
+ *
+ * Inputs:
+ * stat: rx_ctl_dat_fifo_stat_t to read the errors to
+ * valid fields in rx_ctl_dat_fifo_stat_t structure are:
+ * zcp_eop_err, ipp_eop_err, id_mismatch.
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_rxdma_rxctl_fifo_error_intr_get(npi_handle_t handle,
+ rx_ctl_dat_fifo_stat_t *stat)
+{
+ uint64_t offset = RX_CTL_DAT_FIFO_STAT_REG;
+ NXGE_REG_RD64(handle, offset, &stat->value);
+ return (NPI_SUCCESS);
+}
+
+
+
+npi_status_t
+npi_rxdma_rdc_rcr_pktread_update(npi_handle_t handle, uint8_t channel,
+ uint16_t pkts_read)
+{
+
+ rx_dma_ctl_stat_t cs;
+ uint16_t min_read = 0;
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdc_rcr_pktread_update ",
+ " channel %d", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ if ((pkts_read < min_read) && (pkts_read > 512)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdc_rcr_pktread_update ",
+ " pkts %d out of bound", pkts_read));
+ return (NPI_RXDMA_OPCODE_INVALID(pkts_read));
+ }
+
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.ldw.pktread = pkts_read;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG,
+ channel, cs.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_rxdma_rdc_rcr_bufread_update(npi_handle_t handle, uint8_t channel,
+ uint16_t bufs_read)
+{
+
+ rx_dma_ctl_stat_t cs;
+ uint16_t min_read = 0;
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdc_rcr_bufread_update ",
+ " channel %d", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ if ((bufs_read < min_read) && (bufs_read > 512)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdc_rcr_bufread_update ",
+ " bufs read %d out of bound", bufs_read));
+ return (NPI_RXDMA_OPCODE_INVALID(bufs_read));
+ }
+
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.ldw.ptrread = bufs_read;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG,
+ channel, cs.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+
+npi_status_t
+npi_rxdma_rdc_rcr_read_update(npi_handle_t handle, uint8_t channel,
+ uint16_t pkts_read, uint16_t bufs_read)
+{
+
+ rx_dma_ctl_stat_t cs;
+
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_rdc_rcr_read_update ",
+ " channel %d", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_rdc_rcr_read_update "
+ " bufs read %d pkt read %d",
+ bufs_read, pkts_read));
+
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_rdc_rcr_read_update: "
+ " value: 0x%llx bufs read %d pkt read %d",
+ cs.value,
+ cs.bits.ldw.ptrread, cs.bits.ldw.pktread));
+
+ cs.bits.ldw.pktread = pkts_read;
+ cs.bits.ldw.ptrread = bufs_read;
+
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG,
+ channel, cs.value);
+
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+
+ NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL,
+ " npi_rxdma_rdc_rcr_read_update: read back after update "
+ " value: 0x%llx bufs read %d pkt read %d",
+ cs.value,
+ cs.bits.ldw.ptrread, cs.bits.ldw.pktread));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_rxdma_channel_mex_set():
+ * This function is called to arm the DMA channel with
+ * mailbox updating capability. Software needs to rearm
+ * for each update by writing to the control and status register.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ *
+ * Return:
+ * NPI_SUCCESS - If enable channel with mailbox update
+ * is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_mex_set(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_MEX_SET, channel));
+}
+
+/*
+ * npi_rxdma_channel_rcrto_clear():
+ * This function is called to reset RCRTO bit to 0.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_rcrto_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_RCRTO_CLEAR, channel));
+}
+
+/*
+ * npi_rxdma_channel_pt_drop_pkt_clear():
+ * This function is called to clear the port drop packet bit (debug).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_pt_drop_pkt_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_PT_DROP_PKT_CLEAR,
+ channel));
+}
+
+/*
+ * npi_rxdma_channel_wred_drop_clear():
+ * This function is called to wred drop bit (debug only).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_wred_dop_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_WRED_DROP_CLEAR,
+ channel));
+}
+
+/*
+ * npi_rxdma_channel_rcr_shfull_clear():
+ * This function is called to clear RCR shadow full bit.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_rcr_shfull_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_RCR_SFULL_CLEAR,
+ channel));
+}
+
+/*
+ * npi_rxdma_channel_rcrfull_clear():
+ * This function is called to clear RCR full bit.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_rcr_full_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_RCR_FULL_CLEAR,
+ channel));
+}
+
+npi_status_t
+npi_rxdma_channel_rbr_empty_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle,
+ RXDMA_RBR_EMPTY_CLEAR, channel));
+}
+
+npi_status_t
+npi_rxdma_channel_cs_clear_all(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_rxdma_channel_control(handle, RXDMA_CS_CLEAR_ALL, channel));
+}
+
+/*
+ * npi_rxdma_channel_control():
+ * This function is called to control a receive DMA channel
+ * for arming the channel with mailbox updates, resetting
+ * various event status bits (control and status register).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * control - NPI defined control type supported:
+ * - RXDMA_MEX_SET
+ * - RXDMA_RCRTO_CLEAR
+ * - RXDMA_PT_DROP_PKT_CLEAR
+ * - RXDMA_WRED_DROP_CLEAR
+ * - RXDMA_RCR_SFULL_CLEAR
+ * - RXDMA_RCR_FULL_CLEAR
+ * - RXDMA_RBR_PRE_EMPTY_CLEAR
+ * - RXDMA_RBR_EMPTY_CLEAR
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_channel_control(npi_handle_t handle, rxdma_cs_cntl_t control,
+ uint8_t channel)
+{
+
+ rx_dma_ctl_stat_t cs;
+
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_rxdma_channel_control",
+ " channel", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (control) {
+ case RXDMA_MEX_SET:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.mex = 1;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG,
+ channel, cs.value);
+ break;
+
+ case RXDMA_RCRTO_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.rcrto = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_PT_DROP_PKT_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.port_drop_pkt = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_WRED_DROP_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.wred_drop = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_RCR_SFULL_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.rcr_shadow_full = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_RCR_FULL_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.rcrfull = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_RBR_PRE_EMPTY_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.rbr_pre_empty = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_RBR_EMPTY_CLEAR:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ cs.bits.hdw.rbr_empty = 1;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ case RXDMA_CS_CLEAR_ALL:
+ cs.value = 0;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_channel_control",
+ "control", control));
+ return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_rxdma_control_status():
+ * This function is called to operate on the control
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware control and status
+ * OP_SET: set hardware control and status
+ * OP_UPDATE: update hardware control and status.
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cs_p - pointer to hardware defined control and status
+ * structure.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_control_status(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, p_rx_dma_ctl_stat_t cs_p)
+{
+ int status = NPI_SUCCESS;
+ rx_dma_ctl_stat_t cs;
+
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_control_status",
+ "channel", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs_p->value);
+ break;
+
+ case OP_SET:
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs_p->value);
+ break;
+
+ case OP_UPDATE:
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel,
+ &cs.value);
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs_p->value | cs.value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_control_status",
+ "control", op_mode));
+ return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_rxdma_event_mask():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * mask_p - pointer to hardware defined event mask
+ * structure.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_event_mask(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, p_rx_dma_ent_msk_t mask_p)
+{
+ int status = NPI_SUCCESS;
+ rx_dma_ent_msk_t mask;
+
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_event_mask",
+ "channel", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel,
+ &mask_p->value);
+ break;
+
+ case OP_SET:
+ RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel,
+ mask_p->value);
+ break;
+
+ case OP_UPDATE:
+ RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel,
+ &mask.value);
+ RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel,
+ mask_p->value | mask.value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_event_mask",
+ "eventmask", op_mode));
+ return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_rxdma_event_mask_config():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cfgp - pointer to NPI defined event mask
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_rxdma_event_mask_config(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, rxdma_ent_msk_cfg_t *mask_cfgp)
+{
+ int status = NPI_SUCCESS;
+ uint64_t value;
+
+ if (!RXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_event_mask_config",
+ "channel", channel));
+ return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel,
+ mask_cfgp);
+ break;
+
+ case OP_SET:
+ RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel,
+ *mask_cfgp);
+ break;
+
+ case OP_UPDATE:
+ RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel, &value);
+ RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel,
+ *mask_cfgp | value);
+ break;
+
+ case OP_CLEAR:
+ RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel,
+ CFG_RXDMA_MASK_ALL);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_rxdma_event_mask_config",
+ "eventmask", op_mode));
+ return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.h b/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.h
new file mode 100644
index 0000000000..ebf96c94e9
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_rxdma.h
@@ -0,0 +1,1335 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_RXDMA_H
+#define _NPI_RXDMA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+
+#include "nxge_defs.h"
+#include "nxge_hw.h"
+#include <nxge_rxdma_hw.h>
+
+/*
+ * Register offset (0x200 bytes for each channel) for receive ring registers.
+ */
+#define NXGE_RXDMA_OFFSET(x, v, channel) (x + \
+ (!v ? DMC_OFFSET(channel) : \
+ RDMC_PIOVADDR_OFFSET(channel)))
+
+
+#define REG_FZC_RDC_OFFSET(reg, rdc) (reg + RX_LOG_DMA_OFFSET(rdc))
+
+#define REG_RDC_TABLE_OFFSET(table) \
+ (RDC_TBL_REG + table * (NXGE_MAX_RDCS * 8))
+
+#define RXDMA_REG_READ64(handle, reg, channel, data_p) {\
+ NXGE_REG_RD64(handle, (NXGE_RXDMA_OFFSET(reg, handle.is_vraddr,\
+ channel)), (data_p))\
+}
+
+#define RXDMA_REG_READ32(handle, reg, channel) \
+ NXGE_NPI_PIO_READ32(handle, (NXGE_RXDMA_OFFSET(reg, handle.is_vraddr,\
+ channel)))
+
+
+#define RXDMA_REG_WRITE64(handle, reg, channel, data) {\
+ NXGE_REG_WR64(handle, (NXGE_RXDMA_OFFSET(reg, handle.is_vraddr,\
+ channel)), (data))\
+}
+
+/*
+ * RX NPI error codes
+ */
+#define RXDMA_ER_ST (RXDMA_BLK_ID << NPI_BLOCK_ID_SHIFT)
+#define RXDMA_ID_SHIFT(n) (n << NPI_PORT_CHAN_SHIFT)
+
+
+#define NPI_RXDMA_ERROR RXDMA_ER_ST
+
+#define NPI_RXDMA_SW_PARAM_ERROR (NPI_RXDMA_ERROR | 0x40)
+#define NPI_RXDMA_HW_ERROR (NPI_RXDMA_ERROR | 0x80)
+
+#define NPI_RXDMA_RDC_INVALID (NPI_RXDMA_ERROR | CHANNEL_INVALID)
+#define NPI_RXDMA_PAGE_INVALID (NPI_RXDMA_ERROR | LOGICAL_PAGE_INVALID)
+#define NPI_RXDMA_RESET_ERR (NPI_RXDMA_HW_ERROR | RESET_FAILED)
+#define NPI_RXDMA_DISABLE_ERR (NPI_RXDMA_HW_ERROR | 0x0000a)
+#define NPI_RXDMA_ENABLE_ERR (NPI_RXDMA_HW_ERROR | 0x0000b)
+#define NPI_RXDMA_FUNC_INVALID (NPI_RXDMA_SW_PARAM_ERROR | 0x0000a)
+#define NPI_RXDMA_BUFSZIE_INVALID (NPI_RXDMA_SW_PARAM_ERROR | 0x0000b)
+#define NPI_RXDMA_RBRSZIE_INVALID (NPI_RXDMA_SW_PARAM_ERROR | 0x0000c)
+#define NPI_RXDMA_RCRSZIE_INVALID (NPI_RXDMA_SW_PARAM_ERROR | 0x0000d)
+#define NPI_RXDMA_PORT_INVALID (NPI_RXDMA_ERROR | PORT_INVALID)
+#define NPI_RXDMA_TABLE_INVALID (NPI_RXDMA_ERROR | RDC_TAB_INVALID)
+
+#define NPI_RXDMA_CHANNEL_INVALID(n) (RXDMA_ID_SHIFT(n) | \
+ NPI_RXDMA_ERROR | CHANNEL_INVALID)
+#define NPI_RXDMA_OPCODE_INVALID(n) (RXDMA_ID_SHIFT(n) | \
+ NPI_RXDMA_ERROR | OPCODE_INVALID)
+
+
+#define NPI_RXDMA_ERROR_ENCODE(err, rdc) \
+ (RXDMA_ID_SHIFT(rdc) | RXDMA_ER_ST | err)
+
+
+#define RXDMA_CHANNEL_VALID(rdc) \
+ ((rdc < NXGE_MAX_RDCS))
+
+#define RXDMA_PORT_VALID(port) \
+ ((port < MAX_PORTS_PER_NXGE))
+
+#define RXDMA_TABLE_VALID(table) \
+ ((table < NXGE_MAX_RDC_GROUPS))
+
+
+#define RXDMA_PAGE_VALID(page) \
+ ((page == 0) || (page == 1))
+
+#define RXDMA_BUFF_OFFSET_VALID(offset) \
+ ((offset == SW_OFFSET_NO_OFFSET) || \
+ (offset == SW_OFFSET_64) || \
+ (offset == SW_OFFSET_128))
+
+
+#define RXDMA_RCR_TO_VALID(tov) ((tov) && (tov < 64))
+#define RXDMA_RCR_THRESH_VALID(thresh) ((thresh) && (thresh < 512))
+
+
+/*
+ * RXDMA NPI defined control types.
+ */
+typedef enum _rxdma_cs_cntl_e {
+ RXDMA_CS_CLEAR_ALL = 0x1,
+ RXDMA_MEX_SET = 0x2,
+ RXDMA_RCRTO_CLEAR = 0x8,
+ RXDMA_PT_DROP_PKT_CLEAR = 0x10,
+ RXDMA_WRED_DROP_CLEAR = 0x20,
+ RXDMA_RCR_SFULL_CLEAR = 0x40,
+ RXDMA_RCR_FULL_CLEAR = 0x80,
+ RXDMA_RBR_PRE_EMPTY_CLEAR = 0x100,
+ RXDMA_RBR_EMPTY_CLEAR = 0x200
+} rxdma_cs_cntl_t;
+
+/*
+ * RXDMA NPI defined event masks (mapped to the hardware defined masks).
+ */
+typedef enum _rxdma_ent_msk_cfg_e {
+ CFG_RXDMA_ENT_MSK_CFIGLOGPGE_MASK = RX_DMA_ENT_MSK_CFIGLOGPGE_MASK,
+ CFG_RXDMA_ENT_MSK_RBRLOGPGE_MASK = RX_DMA_ENT_MSK_RBRLOGPGE_MASK,
+ CFG_RXDMA_ENT_MSK_RBRFULL_MASK = RX_DMA_ENT_MSK_RBRFULL_MASK,
+ CFG_RXDMA_ENT_MSK_RBREMPTY_MASK = RX_DMA_ENT_MSK_RBREMPTY_MASK,
+ CFG_RXDMA_ENT_MSK_RCRFULL_MASK = RX_DMA_ENT_MSK_RCRFULL_MASK,
+ CFG_RXDMA_ENT_MSK_RCRINCON_MASK = RX_DMA_ENT_MSK_RCRINCON_MASK,
+ CFG_RXDMA_ENT_MSK_CONFIG_ERR = RX_DMA_ENT_MSK_CONFIG_ERR_MASK,
+ CFG_RXDMA_ENT_MSK_RCR_SH_FULL_MASK = RX_DMA_ENT_MSK_RCRSH_FULL_MASK,
+ CFG_RXDMA_ENT_MSK_RBR_PRE_EMTY_MASK = RX_DMA_ENT_MSK_RBR_PRE_EMPTY_MASK,
+ CFG_RXDMA_ENT_MSK_WRED_DROP_MASK = RX_DMA_ENT_MSK_WRED_DROP_MASK,
+ CFG_RXDMA_ENT_MSK_PT_DROP_PKT_MASK = RX_DMA_ENT_MSK_PTDROP_PKT_MASK,
+ CFG_RXDMA_ENT_MSK_RBR_PRE_PAR_MASK = RX_DMA_ENT_MSK_RBR_PRE_PAR_MASK,
+ CFG_RXDMA_ENT_MSK_RCR_SHA_PAR_MASK = RX_DMA_ENT_MSK_RCR_SHA_PAR_MASK,
+ CFG_RXDMA_ENT_MSK_RCRTO_MASK = RX_DMA_ENT_MSK_RCRTO_MASK,
+ CFG_RXDMA_ENT_MSK_THRES_MASK = RX_DMA_ENT_MSK_THRES_MASK,
+ CFG_RXDMA_ENT_MSK_DC_FIFO_ERR_MASK = RX_DMA_ENT_MSK_DC_FIFO_ERR_MASK,
+ CFG_RXDMA_ENT_MSK_RCR_ACK_ERR_MASK = RX_DMA_ENT_MSK_RCR_ACK_ERR_MASK,
+ CFG_RXDMA_ENT_MSK_RSP_DAT_ERR_MASK = RX_DMA_ENT_MSK_RSP_DAT_ERR_MASK,
+ CFG_RXDMA_ENT_MSK_BYTE_EN_BUS_MASK = RX_DMA_ENT_MSK_BYTE_EN_BUS_MASK,
+ CFG_RXDMA_ENT_MSK_RSP_CNT_ERR_MASK = RX_DMA_ENT_MSK_RSP_CNT_ERR_MASK,
+ CFG_RXDMA_ENT_MSK_RBR_TMOUT_MASK = RX_DMA_ENT_MSK_RBR_TMOUT_MASK,
+
+ CFG_RXDMA_MASK_ALL = (RX_DMA_ENT_MSK_CFIGLOGPGE_MASK |
+ RX_DMA_ENT_MSK_RBRLOGPGE_MASK |
+ RX_DMA_ENT_MSK_RBRFULL_MASK |
+ RX_DMA_ENT_MSK_RBREMPTY_MASK |
+ RX_DMA_ENT_MSK_RCRFULL_MASK |
+ RX_DMA_ENT_MSK_RCRINCON_MASK |
+ RX_DMA_ENT_MSK_CONFIG_ERR_MASK |
+ RX_DMA_ENT_MSK_RCRSH_FULL_MASK |
+ RX_DMA_ENT_MSK_RBR_PRE_EMPTY_MASK |
+ RX_DMA_ENT_MSK_WRED_DROP_MASK |
+ RX_DMA_ENT_MSK_PTDROP_PKT_MASK |
+ RX_DMA_ENT_MSK_RBR_PRE_PAR_MASK |
+ RX_DMA_ENT_MSK_RCR_SHA_PAR_MASK |
+ RX_DMA_ENT_MSK_RCRTO_MASK |
+ RX_DMA_ENT_MSK_THRES_MASK |
+ RX_DMA_ENT_MSK_DC_FIFO_ERR_MASK |
+ RX_DMA_ENT_MSK_RCR_ACK_ERR_MASK |
+ RX_DMA_ENT_MSK_RSP_DAT_ERR_MASK |
+ RX_DMA_ENT_MSK_BYTE_EN_BUS_MASK |
+ RX_DMA_ENT_MSK_RSP_CNT_ERR_MASK |
+ RX_DMA_ENT_MSK_RBR_TMOUT_MASK)
+} rxdma_ent_msk_cfg_t;
+
+
+
+typedef union _addr44 {
+ uint64_t addr;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t rsrvd:20;
+ uint32_t hdw:12;
+ uint32_t ldw;
+#else
+ uint32_t ldw;
+ uint32_t hdw:12;
+ uint32_t rsrvd:20;
+#endif
+ } bits;
+} addr44_t;
+
+
+/*
+ * npi_rxdma_cfg_default_port_rdc()
+ * Set the default rdc for the port
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * portnm: Physical Port Number
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ * NPI_RXDMA_PORT_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_default_port_rdc(npi_handle_t,
+ uint8_t, uint8_t);
+
+/*
+ * npi_rxdma_cfg_rdc_table()
+ * Configure/populate the RDC table
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * table: RDC Group Number
+ * rdc[]: Array of RX DMA Channels
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_TABLE_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_table(npi_handle_t,
+ uint8_t, uint8_t []);
+
+npi_status_t npi_rxdma_cfg_rdc_table_default_rdc(npi_handle_t,
+ uint8_t, uint8_t);
+npi_status_t npi_rxdma_cfg_rdc_rcr_timeout_disable(npi_handle_t,
+ uint8_t);
+
+
+/*
+ * npi_rxdma_32bitmode_enable()
+ * Enable 32 bit mode
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_32bitmode_enable(npi_handle_t);
+
+
+/*
+ * npi_rxdma_32bitmode_disable()
+ * disable 32 bit mode
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ *
+ */
+
+
+npi_status_t npi_rxdma_cfg_32bitmode_disable(npi_handle_t);
+
+/*
+ * npi_rxdma_cfg_ram_access_enable()
+ * Enable PIO access to shadow and prefetch memory.
+ * In the case of DMA errors, software may need to
+ * initialize the shadow and prefetch memories to
+ * sane value (may be clear it) before re-enabling
+ * the DMA channel.
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_ram_access_enable(npi_handle_t);
+
+
+/*
+ * npi_rxdma_cfg_ram_access_disable()
+ * Disable PIO access to shadow and prefetch memory.
+ * This is the normal operation mode.
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_ram_access_disable(npi_handle_t);
+
+
+/*
+ * npi_rxdma_cfg_clock_div_set()
+ * init the clock division, used for RX timers
+ * This determines the granularity of RX DMA countdown timers
+ * It depends on the system clock. For example if the system
+ * clock is 300 MHz, a value of 30000 will yield a granularity
+ * of 100usec.
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * count: System clock divider
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_clock_div_set(npi_handle_t, uint16_t);
+
+/*
+ * npi_rxdma_cfg_red_rand_init()
+ * init the WRED Discard
+ * By default, it is enabled
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * init_value: WRED init value
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_red_rand_init(npi_handle_t, uint16_t);
+
+/*
+ * npi_rxdma_cfg_wred_disable()
+ * init the WRED Discard
+ * By default, it is enabled
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+
+npi_status_t npi_rxdma_cfg_wred_disable(npi_handle_t);
+
+/*
+ * npi_rxdma_cfg_wred_param()
+ * COnfigure per rxdma channel WRED parameters
+ * By default, it is enabled
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * rdc: RX DMA Channel number
+ * wred_params: WRED configuration parameters
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+
+
+npi_status_t npi_rxdma_cfg_wred_param(npi_handle_t, uint8_t,
+ rdc_red_para_t *);
+
+
+/*
+ * npi_rxdma_port_ddr_weight
+ * Set the DDR weight for a port.
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * portnm: Physical Port Number
+ * weight: Port relative weight (in approx. bytes)
+ * Default values are:
+ * 0x400 (port 0 and 1) corresponding to 10 standard
+ * size (1500 bytes) Frames
+ * 0x66 (port 2 and 3) corresponding to 10% 10Gig ports
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_port_ddr_weight(npi_handle_t,
+ uint8_t, uint32_t);
+
+
+/*
+ * npi_rxdma_port_usage_get()
+ * Gets the port usage, in terms of 16 byte blocks
+ *
+ * NOTE: The register count is cleared upon reading.
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * portnm: Physical Port Number
+ * blocks: ptr to save current count.
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_HW_ERR
+ * NPI_SW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_port_usage_get(npi_handle_t,
+ uint8_t, uint32_t *);
+
+
+/*
+ * npi_rxdma_cfg_logical_page()
+ * Configure per rxdma channel Logical page
+ *
+ * To disable the logical page, set valid = 0;
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * rdc: RX DMA Channel number
+ * page_params: Logical Page configuration parameters
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+
+
+npi_status_t npi_rxdma_cfg_logical_page(npi_handle_t, uint8_t,
+ dma_log_page_t *);
+
+
+/*
+ * npi_rxdma_cfg_logical_page_handle()
+ * Configure per rxdma channel Logical page handle
+ *
+ *
+ * Inputs:
+ * handle: register handle interpreted by the underlying OS
+ * rdc: RX DMA Channel number
+ * pg_handle: Logical Page handle
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+
+npi_status_t npi_rxdma_cfg_logical_page_handle(npi_handle_t, uint8_t,
+ uint64_t);
+
+
+
+
+npi_status_t npi_rxdma_cfg_logical_page_disable(npi_handle_t,
+ uint8_t, uint8_t);
+
+typedef enum _bsize {
+ SIZE_0B = 0x0,
+ SIZE_64B,
+ SIZE_128B,
+ SIZE_192B,
+ SIZE_256B,
+ SIZE_512B,
+ SIZE_1KB,
+ SIZE_2KB,
+ SIZE_4KB,
+ SIZE_8KB,
+ SIZE_16KB,
+ SIZE_32KB
+} bsize_t;
+
+
+
+/*
+ * npi_rxdma_cfg_rdc_ring()
+ * Configure The RDC channel Rcv Buffer Ring
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rdc_params: RDC configuration parameters
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+typedef struct _rdc_desc_cfg_t {
+ uint8_t mbox_enable; /* Enable full (18b) header */
+ uint8_t full_hdr; /* Enable full (18b) header */
+ uint8_t offset; /* 64 byte offsets */
+ uint8_t valid2; /* size 2 is valid */
+ bsize_t size2; /* Size 2 length */
+ uint8_t valid1; /* size 1 is valid */
+ bsize_t size1; /* Size 1 length */
+ uint8_t valid0; /* size 0 is valid */
+ bsize_t size0; /* Size 1 length */
+ bsize_t page_size; /* Page or buffer Size */
+ uint8_t rcr_timeout_enable;
+ uint8_t rcr_timeout;
+ uint16_t rcr_threshold;
+ uint16_t rcr_len; /* RBR Descriptor size (entries) */
+ uint16_t rbr_len; /* RBR Descriptor size (entries) */
+ uint64_t mbox_addr; /* Mailbox Address */
+ uint64_t rcr_addr; /* RCR Address */
+ uint64_t rbr_addr; /* RBB Address */
+} rdc_desc_cfg_t;
+
+
+
+npi_status_t npi_rxdma_cfg_rdc_ring(npi_handle_t, uint8_t,
+ rdc_desc_cfg_t *);
+
+
+
+
+/*
+ * npi_rxdma_rdc_rcr_flush
+ * Forces RX completion ring update
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ *
+ */
+
+#define npi_rxdma_rdc_rcr_flush(handle, rdc) \
+ RXDMA_REG_WRITE64(handle, RCR_FLSH_REG, rdc, \
+ (RCR_FLSH_SET << RCR_FLSH_SHIFT))
+
+
+
+/*
+ * npi_rxdma_rdc_rcr_read_update
+ * Update the number of rcr packets and buffers processed
+ *
+ * Inputs:
+ * channel: RX DMA Channel number
+ * num_pkts: Number of pkts processed by SW.
+ * A packet could constitute multiple
+ * buffers, in case jumbo packets.
+ * num_bufs: Number of buffer processed by SW.
+ *
+ * Return:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rcr_read_update(npi_handle_t, uint8_t,
+ uint16_t, uint16_t);
+/*
+ * npi_rxdma_rdc_rcr_pktread_update
+ * Update the number of packets processed
+ *
+ * Inputs:
+ * channel: RX DMA Channel number
+ * num_pkts: Number ofpkts processed by SW.
+ * A packet could constitute multiple
+ * buffers, in case jumbo packets.
+ *
+ * Return:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rcr_pktread_update(npi_handle_t,
+ uint8_t, uint16_t);
+
+
+
+/*
+ * npi_rxdma_rdc_rcr_bufread_update
+ * Update the number of buffers processed
+ *
+ * Inputs:
+ * channel: RX DMA Channel number
+ * num_bufs: Number of buffer processed by SW. Multiple buffers
+ * could be part of a single packet.
+ *
+ * Return:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rcr_bufread_update(npi_handle_t,
+ uint8_t, uint16_t);
+
+
+
+/*
+ * npi_rxdma_rdc_rbr_kick
+ * Kick RDC RBR
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * num_buffers: Number of Buffers posted to the RBR
+ *
+ * Return:
+ *
+ */
+
+#define npi_rxdma_rdc_rbr_kick(handle, rdc, num_buffers) \
+ RXDMA_REG_WRITE64(handle, RBR_KICK_REG, rdc, num_buffers)
+
+
+/*
+ * npi_rxdma_rdc_rbr_head_get
+ * Gets the current rbr head pointer.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * hdptr ptr to write the rbr head value
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rbr_head_get(npi_handle_t,
+ uint8_t, addr44_t *);
+
+
+
+/*
+ * npi_rxdma_rdc_rbr_stat_get
+ * Returns the RBR stat. The stat consists of the
+ * RX buffers in the ring. It also indicates if there
+ * has been an overflow.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rbr_stat_t: Structure to update stat
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rbr_stat_get(npi_handle_t, uint8_t,
+ rbr_stat_t *);
+
+
+
+/*
+ * npi_rxdma_cfg_rdc_reset
+ * Resets the RDC channel
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_reset(npi_handle_t, uint8_t);
+
+
+/*
+ * npi_rxdma_rdc_enable
+ * Enables the RDC channel
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_enable(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_rdc_disable
+ * Disables the RDC channel
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_disable(npi_handle_t, uint8_t);
+
+
+/*
+ * npi_rxdma_cfg_rdc_rcr_timeout()
+ * Configure The RDC channel completion ring timeout.
+ * If a frame has been received, an event would be
+ * generated atleast at the expiration of the timeout.
+ *
+ * Enables timeout by default.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rcr_timeout: Completion Ring timeout value
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_rcr_timeout(npi_handle_t, uint8_t,
+ uint8_t);
+
+
+/*
+ * npi_rxdma_cfg_rdc_rcr_threshold()
+ * Configure The RDC channel completion ring threshold.
+ * An event would be If the number of frame received,
+ * surpasses the threshold value
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rcr_threshold: Completion Ring Threshold count
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_SW_ERR
+ * NPI_HW_ERR
+ *
+ */
+
+npi_status_t npi_rxdma_cfg_rdc_rcr_threshold(npi_handle_t, uint8_t,
+ uint16_t);
+
+
+npi_status_t npi_rxdma_cfg_rdc_rcr_timeout_disable(npi_handle_t, uint8_t);
+
+typedef struct _rdc_error_stat_t {
+ uint8_t fault:1;
+ uint8_t multi_fault:1;
+ uint8_t rbr_fault:1;
+ uint8_t buff_fault:1;
+ uint8_t rcr_fault:1;
+ addr44_t fault_addr;
+} rdc_error_stat_t;
+
+#if OLD
+/*
+ * npi_rxdma_rdc_error_stat_get
+ * Gets the current Error stat for the RDC.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * error_stat Structure to write current RDC Error stat
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_error_stat_get(npi_handle_t,
+ uint8_t, rdc_error_stat_t *);
+
+#endif
+
+/*
+ * npi_rxdma_rdc_rcr_tail_get
+ * Gets the current RCR tail address for the RDC.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * tail_addr Structure to write current RDC RCR tail address
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_rcr_tail_get(npi_handle_t,
+ uint8_t, addr44_t *);
+
+
+npi_status_t npi_rxdma_rdc_rcr_qlen_get(npi_handle_t,
+ uint8_t, uint16_t *);
+
+
+
+typedef struct _rdc_discard_stat_t {
+ uint8_t nobuf_ovflow;
+ uint8_t red_ovflow;
+ uint32_t nobuf_discard;
+ uint32_t red_discard;
+} rdc_discard_stat_t;
+
+
+/*
+ * npi_rxdma_rdc_discard_stat_get
+ * Gets the current discrad stats for the RDC.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rcr_stat Structure to write current RDC discard stat
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rxdma_rdc_discard_stat_get(npi_handle_t,
+ uint8_t, rdc_discard_stat_t);
+
+
+/*
+ * npi_rx_port_discard_stat_get
+ * Gets the current input (IPP) discrad stats for the rx port.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rx_disc_cnt_t Structure to write current RDC discard stat
+ *
+ * Return:
+ *
+ */
+
+npi_status_t npi_rx_port_discard_stat_get(npi_handle_t,
+ uint8_t,
+ rx_disc_cnt_t *);
+
+
+/*
+ * npi_rxdma_red_discard_stat_get
+ * Gets the current discrad count due RED
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rx_disc_cnt_t Structure to write current RDC discard stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_red_discard_stat_get(npi_handle_t, uint8_t,
+ rx_disc_cnt_t *);
+
+
+
+/*
+ * npi_rxdma_red_discard_oflow_clear
+ * Clear RED discard counter overflow bit
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_red_discard_oflow_clear(npi_handle_t,
+ uint8_t);
+
+
+
+
+/*
+ * npi_rxdma_misc_discard_stat_get
+ * Gets the current discrad count for the rdc due to
+ * buffer pool empty
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ * rx_disc_cnt_t Structure to write current RDC discard stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_misc_discard_stat_get(npi_handle_t, uint8_t,
+ rx_disc_cnt_t *);
+
+
+
+/*
+ * npi_rxdma_red_discard_oflow_clear
+ * Clear RED discard counter overflow bit
+ * clear the overflow bit for buffer pool empty discrad counter
+ * for the rdc
+ *
+ *
+ * Inputs:
+ * rdc: RX DMA Channel number
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_misc_discard_oflow_clear(npi_handle_t,
+ uint8_t);
+
+
+
+/*
+ * npi_rxdma_ring_perr_stat_get
+ * Gets the current RDC Memory parity error
+ * The counter overflow bit is cleared, if it has been set.
+ *
+ * Inputs:
+ * pre_cnt: Structure to write current RDC Prefetch memory
+ * Parity Error stat
+ * sha_cnt: Structure to write current RDC Shadow memory
+ * Parity Error stat
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_ring_perr_stat_get(npi_handle_t,
+ rdmc_par_err_log_t *,
+ rdmc_par_err_log_t *);
+
+
+/*
+ * npi_rxdma_ring_perr_stat_get
+ * Clear RDC Memory Parity Error counter overflow bits
+ *
+ * Inputs:
+ * Return:
+ * NPI_SUCCESS
+ *
+ */
+
+npi_status_t npi_rxdma_ring_perr_stat_clear(npi_handle_t);
+
+
+/* Access the RDMC Memory: used for debugging */
+
+npi_status_t npi_rxdma_rdmc_memory_io(npi_handle_t,
+ rdmc_mem_access_t *, uint8_t);
+
+
+
+/*
+ * npi_rxdma_rxctl_fifo_error_intr_set
+ * Configure The RX ctrl fifo error interrupt generation
+ *
+ * Inputs:
+ * mask: rx_ctl_dat_fifo_mask_t specifying the errors
+ *
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+
+npi_status_t npi_rxdma_rxctl_fifo_error_intr_set(npi_handle_t,
+ rx_ctl_dat_fifo_mask_t *);
+
+/*
+ * npi_rxdma_rxctl_fifo_error_status_get
+ * Read The RX ctrl fifo error Status
+ *
+ * Inputs:
+ * stat: rx_ctl_dat_fifo_stat_t to read the errors to
+ * valid fields in rx_ctl_dat_fifo_stat_t structure are:
+ * zcp_eop_err, ipp_eop_err, id_mismatch.
+ * Return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+
+npi_status_t npi_rxdma_rxctl_fifo_error_status_get(npi_handle_t,
+ rx_ctl_dat_fifo_stat_t *);
+
+
+/*
+ * npi_rxdma_channel_mex_set():
+ * This function is called to arm the DMA channel with
+ * mailbox updating capability. Software needs to rearm
+ * for each update by writing to the control and status register.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ *
+ * Return:
+ * NPI_SUCCESS - If enable channel with mailbox update
+ * is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_mex_set(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_rcrto_clear():
+ * This function is called to reset RCRTO bit to 0.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_rcrto_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_pt_drop_pkt_clear():
+ * This function is called to clear the port drop packet bit (debug).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_pt_drop_pkt_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_wred_drop_clear():
+ * This function is called to wred drop bit (debug only).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_wred_drop_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_rcr_shfull_clear():
+ * This function is called to clear RCR shadow full bit.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_rcr_shfull_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_rcrfull_clear():
+ * This function is called to clear RCR full bit.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_rcrfull_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_rbr_pre_empty_clear():
+ * This function is called to control a receive DMA channel
+ * for arming the channel with mailbox updates, resetting
+ * various event status bits (control and status register).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * control - NPI defined control type supported:
+ * - RXDMA_MEX_SET
+ * - RXDMA_RCRTO_CLEAR
+ * - RXDMA_PT_DROP_PKT_CLEAR
+ * - RXDMA_WRED_DROP_CLEAR
+ * - RXDMA_RCR_SFULL_CLEAR
+ * - RXDMA_RCR_FULL_CLEAR
+ * - RXDMA_RBR_PRE_EMPTY_CLEAR
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_rbr_pre_empty_clear(npi_handle_t, uint8_t);
+
+/*
+ * npi_rxdma_channel_control():
+ * This function is called to control a receive DMA channel
+ * for arming the channel with mailbox updates, resetting
+ * various event status bits (control and status register).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * control - NPI defined control type supported:
+ * - RXDMA_MEX_SET
+ * - RXDMA_RCRTO_CLEAR
+ * - RXDMA_PT_DROP_PKT_CLEAR
+ * - RXDMA_WRED_DROP_CLEAR
+ * - RXDMA_RCR_SFULL_CLEAR
+ * - RXDMA_RCR_FULL_CLEAR
+ * - RXDMA_RBR_PRE_EMPTY_CLEAR
+ * channel - logical RXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_channel_control(npi_handle_t,
+ rxdma_cs_cntl_t, uint8_t);
+
+/*
+ * npi_rxdma_control_status():
+ * This function is called to operate on the control
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware control and status
+ * OP_SET: set hardware control and status
+ * OP_UPDATE: update hardware control and status.
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cs_p - pointer to hardware defined control and status
+ * structure.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_control_status(npi_handle_t, io_op_t,
+ uint8_t, p_rx_dma_ctl_stat_t);
+
+/*
+ * npi_rxdma_event_mask():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * mask_p - pointer to hardware defined event mask
+ * structure.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_event_mask(npi_handle_t, io_op_t,
+ uint8_t, p_rx_dma_ent_msk_t);
+
+/*
+ * npi_rxdma_event_mask_config():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware RXDMA channel from 0 to 23.
+ * cfgp - pointer to NPI defined event mask
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_RXDMA_OPCODE_INVALID -
+ * NPI_RXDMA_CHANNEL_INVALID -
+ */
+npi_status_t npi_rxdma_event_mask_config(npi_handle_t, io_op_t,
+ uint8_t, rxdma_ent_msk_cfg_t *);
+
+
+/*
+ * npi_rxdma_dump_rdc_regs
+ * Dumps the contents of rdc csrs and fzc registers
+ *
+ * Input:
+ * rdc: RX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_dump_rdc_regs(npi_handle_t, uint8_t);
+
+
+/*
+ * npi_rxdma_dump_fzc_regs
+ * Dumps the contents of rdc csrs and fzc registers
+ *
+ * Input:
+ * rdc: RX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_RXDMA_RDC_INVALID
+ *
+ */
+
+npi_status_t npi_rxdma_dump_fzc_regs(npi_handle_t);
+
+npi_status_t npi_rxdma_channel_rbr_empty_clear(npi_handle_t,
+ uint8_t);
+npi_status_t npi_rxdma_rxctl_fifo_error_intr_get(npi_handle_t,
+ rx_ctl_dat_fifo_stat_t *);
+
+npi_status_t npi_rxdma_rxctl_fifo_error_intr_set(npi_handle_t,
+ rx_ctl_dat_fifo_mask_t *);
+
+npi_status_t npi_rxdma_dump_rdc_table(npi_handle_t, uint8_t);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_RXDMA_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_txc.c b/usr/src/uts/sun4v/io/nxge/npi/npi_txc.c
new file mode 100644
index 0000000000..e6bef7b7c6
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_txc.c
@@ -0,0 +1,1144 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_txc.h>
+
+/*
+ * Transmit Controller (TXC) Functions.
+ */
+
+uint64_t txc_fzc_dmc_offset[] = {
+ TXC_DMA_MAX_BURST_REG,
+ TXC_DMA_MAX_LENGTH_REG
+};
+
+const char *txc_fzc_dmc_name[] = {
+ "TXC_DMA_MAX_BURST_REG",
+ "TXC_DMA_MAX_LENGTH_REG"
+};
+
+uint64_t txc_fzc_offset [] = {
+ TXC_CONTROL_REG,
+ TXC_TRAINING_REG,
+ TXC_DEBUG_SELECT_REG,
+ TXC_MAX_REORDER_REG,
+ TXC_INT_STAT_DBG_REG,
+ TXC_INT_STAT_REG,
+ TXC_INT_MASK_REG
+};
+
+const char *txc_fzc_name [] = {
+ "TXC_CONTROL_REG",
+ "TXC_TRAINING_REG",
+ "TXC_DEBUG_SELECT_REG",
+ "TXC_MAX_REORDER_REG",
+ "TXC_INT_STAT_DBG_REG",
+ "TXC_INT_STAT_REG",
+ "TXC_INT_MASK_REG"
+};
+
+uint64_t txc_fzc_port_offset[] = {
+ TXC_PORT_CTL_REG,
+ TXC_PORT_DMA_ENABLE_REG,
+ TXC_PKT_STUFFED_REG,
+ TXC_PKT_XMIT_REG,
+ TXC_ROECC_CTL_REG,
+ TXC_ROECC_ST_REG,
+ TXC_RO_DATA0_REG,
+ TXC_RO_DATA1_REG,
+ TXC_RO_DATA2_REG,
+ TXC_RO_DATA3_REG,
+ TXC_RO_DATA4_REG,
+ TXC_SFECC_CTL_REG,
+ TXC_SFECC_ST_REG,
+ TXC_SF_DATA0_REG,
+ TXC_SF_DATA1_REG,
+ TXC_SF_DATA2_REG,
+ TXC_SF_DATA3_REG,
+ TXC_SF_DATA4_REG,
+ TXC_RO_TIDS_REG,
+ TXC_RO_STATE0_REG,
+ TXC_RO_STATE1_REG,
+ TXC_RO_STATE2_REG,
+ TXC_RO_STATE3_REG,
+ TXC_RO_CTL_REG,
+ TXC_RO_ST_DATA0_REG,
+ TXC_RO_ST_DATA1_REG,
+ TXC_RO_ST_DATA2_REG,
+ TXC_RO_ST_DATA3_REG,
+ TXC_PORT_PACKET_REQ_REG
+};
+
+const char *txc_fzc_port_name[] = {
+ "TXC_PORT_CTL_REG",
+ "TXC_PORT_DMA_ENABLE_REG",
+ "TXC_PKT_STUFFED_REG",
+ "TXC_PKT_XMIT_REG",
+ "TXC_ROECC_CTL_REG",
+ "TXC_ROECC_ST_REG",
+ "TXC_RO_DATA0_REG",
+ "TXC_RO_DATA1_REG",
+ "TXC_RO_DATA2_REG",
+ "TXC_RO_DATA3_REG",
+ "TXC_RO_DATA4_REG",
+ "TXC_SFECC_CTL_REG",
+ "TXC_SFECC_ST_REG",
+ "TXC_SF_DATA0_REG",
+ "TXC_SF_DATA1_REG",
+ "TXC_SF_DATA2_REG",
+ "TXC_SF_DATA3_REG",
+ "TXC_SF_DATA4_REG",
+ "TXC_RO_TIDS_REG",
+ "TXC_RO_STATE0_REG",
+ "TXC_RO_STATE1_REG",
+ "TXC_RO_STATE2_REG",
+ "TXC_RO_STATE3_REG",
+ "TXC_RO_CTL_REG",
+ "TXC_RO_ST_DATA0_REG",
+ "TXC_RO_ST_DATA1_REG",
+ "TXC_RO_ST_DATA2_REG",
+ "TXC_RO_ST_DATA3_REG",
+ "TXC_PORT_PACKET_REQ_REG"
+};
+
+/*
+ * npi_txc_dump_tdc_fzc_regs
+ * Dumps the contents of TXC csrs and fzc registers
+ *
+ * Input:
+ * tdc: TX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_TXC_CHANNEL_INVALID
+ *
+ */
+npi_status_t
+npi_txc_dump_tdc_fzc_regs(npi_handle_t handle, uint8_t tdc)
+{
+ uint64_t value, offset;
+ int num_regs, i;
+
+ if (!TXDMA_CHANNEL_VALID(tdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_txc_dump_tdc_fzc_regs"
+ " Invalid TDC number %d \n",
+ tdc));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(tdc));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXC FZC DMC Register Dump for Channel %d\n",
+ tdc));
+
+ num_regs = sizeof (txc_fzc_dmc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ offset = TXC_FZC_REG_CN_OFFSET(txc_fzc_dmc_offset[i], tdc);
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ offset, txc_fzc_dmc_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXC FZC Register Dump for Channel %d done\n", tdc));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_dump_fzc_regs
+ * Dumps the contents of txc csrs and fzc registers
+ *
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_txc_dump_fzc_regs(npi_handle_t handle)
+{
+
+ uint64_t value;
+ int num_regs, i;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXC FZC Common Register Dump\n"));
+
+ num_regs = sizeof (txc_fzc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ NXGE_REG_RD64(handle, txc_fzc_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ txc_fzc_offset[i], txc_fzc_name[i], value));
+ }
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXC FZC Common Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_dump_port_fzc_regs
+ * Dumps the contents of TXC csrs and fzc registers
+ *
+ * Input:
+ * port: port number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_txc_dump_port_fzc_regs(npi_handle_t handle, uint8_t port)
+{
+ uint64_t value, offset;
+ int num_regs, i;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_dump_port_fzc"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXC FZC PORT Register Dump for port %d\n", port));
+
+ num_regs = sizeof (txc_fzc_port_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ offset = TXC_FZC_REG_PT_OFFSET(txc_fzc_port_offset[i], port);
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ offset, txc_fzc_port_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXC FZC Register Dump for port %d done\n", port));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_dma_max_burst():
+ * This function is called to configure the max burst bytes.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get max burst value
+ * - OP_SET: set max burst value
+ * channel - channel number (0 - 23)
+ * dma_max_burst_p - pointer to store or used for max burst value.
+ * Return:
+ * NPI_SUCCESS - If operation is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_OPCODE_INVALID
+ * NPI_TXC_CHANNEL_INVALID
+ */
+npi_status_t
+npi_txc_dma_max_burst(npi_handle_t handle, io_op_t op_mode, uint8_t channel,
+ uint32_t *dma_max_burst_p)
+{
+ uint64_t val;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_dma_max_burst"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TXC_FZC_REG_READ64(handle, TXC_DMA_MAX_BURST_REG, channel,
+ &val);
+ *dma_max_burst_p = (uint32_t)val;
+ break;
+
+ case OP_SET:
+ TXC_FZC_REG_WRITE64(handle,
+ TXC_DMA_MAX_BURST_REG, channel, *dma_max_burst_p);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_dma_max_burst"
+ " Invalid Input: burst <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXC_OPCODE_INVALID(channel));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_dma_max_burst_set():
+ * This function is called to set the max burst bytes.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * channel - channel number (0 - 23)
+ * max_burst - max burst to set
+ * Return:
+ * NPI_SUCCESS - If operation is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ */
+npi_status_t
+npi_txc_dma_max_burst_set(npi_handle_t handle, uint8_t channel,
+ uint32_t max_burst)
+{
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_dma_max_burst_set"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(channel));
+ }
+
+ TXC_FZC_REG_WRITE64(handle, TXC_DMA_MAX_BURST_REG,
+ channel, (uint64_t)max_burst);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_dma_bytes_transmitted():
+ * This function is called to get # of bytes transmitted by
+ * DMA (hardware register is cleared on read).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * channel - channel number (0 - 23)
+ * dma_bytes_p - pointer to store bytes transmitted.
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_dma_bytes_transmitted(npi_handle_t handle, uint8_t channel,
+ uint32_t *dma_bytes_p)
+{
+ uint64_t val;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_dma_bytes_transmitted"
+ " Invalid Input: channel %d",
+ channel));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(channel));
+ }
+
+ TXC_FZC_REG_READ64(handle, TXC_DMA_MAX_LENGTH_REG, channel, &val);
+ *dma_bytes_p = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_control():
+ * This function is called to get or set the control register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get control register value
+ * OP_SET: set control register value
+ * txc_control_p - pointer to hardware defined data structure.
+ * Return:
+ * NPI_SUCCESS - If operation is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_OPCODE_INVALID
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_control(npi_handle_t handle, io_op_t op_mode,
+ p_txc_control_t txc_control_p)
+{
+ switch (op_mode) {
+ case OP_GET:
+ NXGE_REG_RD64(handle, TXC_CONTROL_REG, &txc_control_p->value);
+ break;
+
+ case OP_SET:
+ NXGE_REG_WR64(handle, TXC_CONTROL_REG,
+ txc_control_p->value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_control"
+ " Invalid Input: control 0x%x",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXC_OPCODE_INVALID(op_mode));
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_global_enable():
+ * This function is called to globally enable TXC.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If enable is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_txc_global_enable(npi_handle_t handle)
+{
+ txc_control_t cntl;
+ uint64_t val;
+
+ cntl.value = 0;
+ cntl.bits.ldw.txc_enabled = 1;
+
+ NXGE_REG_RD64(handle, TXC_CONTROL_REG, &val);
+ NXGE_REG_WR64(handle, TXC_CONTROL_REG, val | cntl.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_global_disable():
+ * This function is called to globally disable TXC.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If disable is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_txc_global_disable(npi_handle_t handle)
+{
+ txc_control_t cntl;
+ uint64_t val;
+
+
+ cntl.value = 0;
+ cntl.bits.ldw.txc_enabled = 0;
+
+ NXGE_REG_RD64(handle, TXC_CONTROL_REG, &val);
+ NXGE_REG_WR64(handle, TXC_CONTROL_REG, val | cntl.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_control_clear():
+ * This function is called to clear all bits.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If reset all bits to 0s is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_txc_control_clear(npi_handle_t handle, uint8_t port)
+{
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_control_clear"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ NXGE_REG_WR64(handle, TXC_PORT_CTL_REG, TXC_PORT_CNTL_CLEAR);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_training_set():
+ * This function is called to set the debug training vector.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * vector - training vector to set.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ */
+npi_status_t
+npi_txc_training_set(npi_handle_t handle, uint32_t vector)
+{
+ NXGE_REG_WR64(handle, TXC_TRAINING_REG, (uint64_t)vector);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_training_get():
+ * This function is called to get the debug training vector.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * vector_p - pointer to store training vector.
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ */
+npi_status_t
+npi_txc_training_get(npi_handle_t handle, uint32_t *vector_p)
+{
+ uint64_t val;
+
+ NXGE_REG_RD64(handle, (TXC_TRAINING_REG & TXC_TRAINING_VECTOR_MASK),
+ &val);
+ *vector_p = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_port_enable():
+ * This function is called to enable a particular port.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * Return:
+ * NPI_SUCCESS - If port is enabled successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_port_enable(npi_handle_t handle, uint8_t port)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_enable:",
+ " Invalid Input port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ NXGE_REG_RD64(handle, TXC_CONTROL_REG, &val);
+ NXGE_REG_WR64(handle, TXC_CONTROL_REG, val | (1 << port));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_port_disable():
+ * This function is called to disable a particular port.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * Return:
+ * NPI_SUCCESS - If port is disabled successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_port_disable(npi_handle_t handle, uint8_t port)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_disable",
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ NXGE_REG_RD64(handle, TXC_CONTROL_REG, &val);
+ NXGE_REG_WR64(handle, TXC_CONTROL_REG, (val & ~(1 << port)));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_port_dma_enable():
+ * This function is called to bind DMA channels (bitmap) to a port.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * port_dma_list_bitmap - channels bitmap
+ * (1 to bind, 0 - 23 bits one bit/channel)
+ * Return:
+ * NPI_SUCCESS - If channels are bound successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_port_dma_enable(npi_handle_t handle, uint8_t port,
+ uint32_t port_dma_list_bitmap)
+{
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_enable",
+ " Invalid Input: port", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_PORT_DMA_ENABLE_REG, port,
+ port_dma_list_bitmap);
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txc_port_dma_list_get(npi_handle_t handle, uint8_t port,
+ uint32_t *port_dma_list_bitmap)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_list_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port, &val);
+ *port_dma_list_bitmap = (uint32_t)(val & TXC_DMA_DMA_LIST_MASK);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_port_dma_channel_enable():
+ * This function is called to bind a channel to a port.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * channel - channel number (0 - 23)
+ * Return:
+ * NPI_SUCCESS - If channel is bound successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID -
+ */
+npi_status_t
+npi_txc_port_dma_channel_enable(npi_handle_t handle, uint8_t port,
+ uint8_t channel)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_enable"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_channel_enable"
+ " Invalid Input: channel <0x%x>", channel));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(channel));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port, &val);
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_PORT_DMA_ENABLE_REG, port,
+ (val | (1 << channel)));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_port_dma_channel_disable():
+ * This function is called to unbind a channel to a port.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * channel - channel number (0 - 23)
+ * Return:
+ * NPI_SUCCESS - If channel is unbound successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID -
+ */
+npi_status_t
+npi_txc_port_dma_channel_disable(npi_handle_t handle, uint8_t port,
+ uint8_t channel)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_disable"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_port_dma_channel_disable"
+ " Invalid Input: channel <0x%x>", channel));
+ return (NPI_FAILURE | NPI_TXC_CHANNEL_INVALID(channel));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port, &val)
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_PORT_DMA_ENABLE_REG, port,
+ val & ~(1 << channel));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_max_reorder_set():
+ * This function is called to set the per port reorder resources
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port to set
+ * reorder - reorder resources (4 bits)
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ */
+npi_status_t
+npi_txc_reorder_set(npi_handle_t handle, uint8_t port, uint8_t *reorder)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_reorder_set"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ /* XXXX sanity check */
+ NXGE_REG_RD64(handle, TXC_MAX_REORDER_REG, &val);
+
+ val |= (*reorder << TXC_MAX_REORDER_SHIFT(port));
+
+ NXGE_REG_WR64(handle, TXC_MAX_REORDER_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_reorder_get():
+ * This function is called to get the txc reorder resources.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port to get
+ * reorder - data to be stored at
+ * Return:
+ * NPI_SUCCESS
+ *
+ * Error:
+ * NPI_FAILURE -
+ */
+npi_status_t
+npi_txc_reorder_get(npi_handle_t handle, uint8_t port, uint32_t *reorder)
+{
+ uint64_t val;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_reorder_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ /* XXXX error check on reorder */
+
+
+ NXGE_REG_RD64(handle, TXC_MAX_REORDER_REG, &val);
+
+ *reorder = (uint8_t)(val >> TXC_MAX_REORDER_SHIFT(port));
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_txc_pkt_stuffed_get():
+ * This function is called to get total # of packets processed
+ * by reorder engine and packetAssy engine.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * pkt_assy_p - packets processed by Assy engine.
+ * pkt_reorder_p - packets processed by reorder engine.
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_pkt_stuffed_get(npi_handle_t handle, uint8_t port,
+ uint32_t *pkt_assy_p, uint32_t *pkt_reorder_p)
+{
+ uint64_t value;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_pkt_stuffed_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_PKT_STUFFED_REG, port, &value);
+ *pkt_assy_p = ((uint32_t)((value & TXC_PKT_STUFF_PKTASY_MASK) >>
+ TXC_PKT_STUFF_PKTASY_SHIFT));
+ *pkt_reorder_p = ((uint32_t)((value & TXC_PKT_STUFF_REORDER_MASK) >>
+ TXC_PKT_STUFF_REORDER_SHIFT));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_pkt_xmt_to_mac_get():
+ * This function is called to get total # of packets transmitted
+ * to the MAC.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number (0 - 3)
+ * mac_bytes_p - bytes transmitted to the MAC.
+ * mac_pkts_p - packets transmitted to the MAC.
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_pkt_xmt_to_mac_get(npi_handle_t handle, uint8_t port,
+ uint32_t *mac_bytes_p, uint32_t *mac_pkts_p)
+{
+ uint64_t value;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_xmt_to_mac_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_PKT_XMIT_REG, port, &value);
+ *mac_pkts_p = ((uint32_t)((value & TXC_PKTS_XMIT_MASK) >>
+ TXC_PKTS_XMIT_SHIFT));
+ *mac_bytes_p = ((uint32_t)((value & TXC_BYTES_XMIT_MASK) >>
+ TXC_BYTES_XMIT_SHIFT));
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_txc_get_ro_states():
+ * This function is called to get TXC's reorder state-machine states.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number
+ * *states - TXC Re-order states.
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+npi_status_t
+npi_txc_ro_states_get(npi_handle_t handle, uint8_t port,
+ txc_ro_states_t *states)
+{
+ txc_ro_ctl_t ctl;
+ txc_ro_tids_t tids;
+ txc_ro_state0_t s0;
+ txc_ro_state1_t s1;
+ txc_ro_state2_t s2;
+ txc_ro_state3_t s3;
+ txc_roecc_st_t ecc;
+ txc_ro_data0_t d0;
+ txc_ro_data1_t d1;
+ txc_ro_data2_t d2;
+ txc_ro_data3_t d3;
+ txc_ro_data4_t d4;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_ro_states_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_ROECC_ST_REG, port, &ecc.value);
+ if ((ecc.bits.ldw.correct_error) || (ecc.bits.ldw.uncorrect_error)) {
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_DATA0_REG, port,
+ &d0.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_DATA1_REG, port,
+ &d1.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_DATA2_REG, port,
+ &d2.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_DATA3_REG, port,
+ &d3.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_DATA4_REG, port,
+ &d4.value);
+ states->d0.value = d0.value;
+ states->d1.value = d1.value;
+ states->d2.value = d2.value;
+ states->d3.value = d3.value;
+ states->d4.value = d4.value;
+
+ ecc.bits.ldw.ecc_address = 0;
+ ecc.bits.ldw.correct_error = 0;
+ ecc.bits.ldw.uncorrect_error = 0;
+ ecc.bits.ldw.clr_st = 1;
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_ST_REG, port,
+ ecc.value);
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_CTL_REG, port, &ctl.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_STATE0_REG, port, &s0.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_STATE1_REG, port, &s1.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_STATE2_REG, port, &s2.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_STATE3_REG, port, &s3.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_RO_TIDS_REG, port, &tids.value);
+
+ states->roecc.value = ctl.value;
+ states->st0.value = s0.value;
+ states->st1.value = s1.value;
+ states->st2.value = s2.value;
+ states->st3.value = s3.value;
+ states->ctl.value = ctl.value;
+ states->tids.value = tids.value;
+
+ ctl.bits.ldw.clr_fail_state = 1;
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_RO_CTL_REG, port, ctl.value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txc_ro_ecc_state_clr(npi_handle_t handle, uint8_t port)
+{
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_ro_ecc_state_clr"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_ST_REG, port, 0);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_sf_states_get():
+ * This function is called to get TXC's store-forward state-machine states.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * port - port number
+ * states - TXC Store-forward states
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXC_PORT_INVALID
+ */
+
+#ifdef lint
+/*ARGSUSED*/
+#endif
+
+npi_status_t
+npi_txc_sf_states_get(npi_handle_t handle, uint8_t port,
+ txc_sf_states_t *states)
+{
+ txc_sfecc_st_t ecc;
+ txc_sf_data0_t d0;
+ txc_sf_data1_t d1;
+ txc_sf_data2_t d2;
+ txc_sf_data3_t d3;
+ txc_sf_data4_t d4;
+
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_sf_states_get"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SFECC_ST_REG, port, &ecc.value);
+ if ((ecc.bits.ldw.correct_error) || (ecc.bits.ldw.uncorrect_error)) {
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SF_DATA0_REG, port,
+ &d0.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SF_DATA1_REG, port,
+ &d1.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SF_DATA2_REG, port,
+ &d2.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SF_DATA3_REG, port,
+ &d3.value);
+ TXC_FZC_CNTL_REG_READ64(handle, TXC_SF_DATA4_REG, port,
+ &d4.value);
+ ecc.bits.ldw.ecc_address = 0;
+ ecc.bits.ldw.correct_error = 0;
+ ecc.bits.ldw.uncorrect_error = 0;
+ ecc.bits.ldw.clr_st = 1;
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_ST_REG, port,
+ ecc.value);
+ }
+
+ states->sfecc.value = ecc.value;
+ states->d0.value = d0.value;
+ states->d1.value = d1.value;
+ states->d2.value = d2.value;
+ states->d3.value = d3.value;
+ states->d4.value = d4.value;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txc_sf_ecc_state_clr(npi_handle_t handle, uint8_t port)
+{
+ if (!IS_PORT_NUM_VALID(port)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txc_sf_ecc_state_clr"
+ " Invalid Input: port <%d>", port));
+ return (NPI_FAILURE | NPI_TXC_PORT_INVALID(port));
+ }
+
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_ST_REG, port, 0);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txc_global_istatus_get():
+ * This function is called to get TXC's global interrupt status.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * istatus - TXC global interrupt status
+ *
+ * Return:
+ */
+
+void
+npi_txc_global_istatus_get(npi_handle_t handle, txc_int_stat_t *istatus)
+{
+ txc_int_stat_t status;
+
+ NXGE_REG_RD64(handle, TXC_INT_STAT_REG, &status.value);
+
+ istatus->value = status.value;
+}
+
+/*
+ * npi_txc_global_istatus_clear():
+ * This function is called to clear TXC's global interrupt status.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * istatus - TXC global interrupt status
+ *
+ * Return:
+ */
+
+void
+npi_txc_global_istatus_clear(npi_handle_t handle, uint64_t istatus)
+{
+ NXGE_REG_WR64(handle, TXC_INT_STAT_REG, istatus);
+}
+
+void
+npi_txc_global_imask_set(npi_handle_t handle, uint8_t portn, uint8_t istatus)
+{
+ uint64_t val;
+
+ NXGE_REG_RD64(handle, TXC_INT_MASK_REG, &val);
+ switch (portn) {
+ case 0:
+ val &= 0xFFFFFF00;
+ val |= istatus & 0x3F;
+ break;
+ case 1:
+ val &= 0xFFFF00FF;
+ val |= (istatus << 8) & 0x3F00;
+ break;
+ case 2:
+ val &= 0xFF00FFFF;
+ val |= (istatus << 16) & 0x3F0000;
+ break;
+ case 3:
+ val &= 0x00FFFFFF;
+ val |= (istatus << 24) & 0x3F000000;
+ break;
+ default:
+ ;
+ }
+ NXGE_REG_WR64(handle, TXC_INT_MASK_REG, val);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_txc.h b/usr/src/uts/sun4v/io/nxge/npi/npi_txc.h
new file mode 100644
index 0000000000..7b3dff9ce2
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_txc.h
@@ -0,0 +1,138 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_TXC_H
+#define _NPI_TXC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_txc_hw.h>
+
+/*
+ * Transmit Controller (TXC) NPI error codes
+ */
+#define TXC_ER_ST (TXC_BLK_ID << NPI_BLOCK_ID_SHIFT)
+#define TXC_ID_SHIFT(n) (n << NPI_PORT_CHAN_SHIFT)
+
+#define NPI_TXC_PORT_INVALID(n) (TXC_ID_SHIFT(n) | IS_PORT |\
+ TXC_ER_ST | PORT_INVALID)
+
+#define NPI_TXC_CHANNEL_INVALID(n) (TXC_ID_SHIFT(n) | IS_PORT |\
+ TXC_ER_ST | CHANNEL_INVALID)
+
+#define NPI_TXC_OPCODE_INVALID(n) (TXC_ID_SHIFT(n) | IS_PORT |\
+ TXC_ER_ST | OPCODE_INVALID)
+
+/*
+ * Register offset (0x1000 bytes for each channel) for TXC registers.
+ */
+#define NXGE_TXC_FZC_OFFSET(x, cn) (x + TXC_FZC_CHANNEL_OFFSET(cn))
+
+/*
+ * Register offset (0x100 bytes for each port) for TXC Function zero
+ * control registers.
+ */
+#define NXGE_TXC_FZC_CNTL_OFFSET(x, port) (x + \
+ TXC_FZC_CNTL_PORT_OFFSET(port))
+/*
+ * PIO macros to read and write the transmit control registers.
+ */
+#define TXC_FZC_REG_READ64(handle, reg, cn, val_p) \
+ NXGE_REG_RD64(handle, \
+ (NXGE_TXC_FZC_OFFSET(reg, cn)), val_p)
+
+#define TXC_FZC_REG_WRITE64(handle, reg, cn, data) \
+ NXGE_REG_WR64(handle, \
+ (NXGE_TXC_FZC_OFFSET(reg, cn)), data)
+
+#define TXC_FZC_CNTL_REG_READ64(handle, reg, port, val_p) \
+ NXGE_REG_RD64(handle, \
+ (NXGE_TXC_FZC_CNTL_OFFSET(reg, port)), val_p)
+
+#define TXC_FZC_CNTL_REG_WRITE64(handle, reg, port, data) \
+ NXGE_REG_WR64(handle, \
+ (NXGE_TXC_FZC_CNTL_OFFSET(reg, port)), data)
+
+/*
+ * TXC (Transmit Controller) prototypes.
+ */
+npi_status_t npi_txc_dma_max_burst(npi_handle_t, io_op_t,
+ uint8_t, uint32_t *);
+npi_status_t npi_txc_dma_max_burst_set(npi_handle_t, uint8_t,
+ uint32_t);
+npi_status_t npi_txc_dma_bytes_transmitted(npi_handle_t,
+ uint8_t, uint32_t *);
+npi_status_t npi_txc_control(npi_handle_t, io_op_t,
+ p_txc_control_t);
+npi_status_t npi_txc_global_enable(npi_handle_t);
+npi_status_t npi_txc_global_disable(npi_handle_t);
+npi_status_t npi_txc_control_clear(npi_handle_t, uint8_t);
+npi_status_t npi_txc_training_set(npi_handle_t, uint32_t);
+npi_status_t npi_txc_training_get(npi_handle_t, uint32_t *);
+npi_status_t npi_txc_port_control_get(npi_handle_t, uint8_t,
+ uint32_t *);
+npi_status_t npi_txc_port_enable(npi_handle_t, uint8_t);
+npi_status_t npi_txc_port_disable(npi_handle_t, uint8_t);
+npi_status_t npi_txc_dma_max_burst(npi_handle_t, io_op_t,
+ uint8_t, uint32_t *);
+npi_status_t npi_txc_port_dma_enable(npi_handle_t, uint8_t,
+ uint32_t);
+npi_status_t npi_txc_port_dma_list_get(npi_handle_t, uint8_t,
+ uint32_t *);
+npi_status_t npi_txc_port_dma_channel_enable(npi_handle_t, uint8_t,
+ uint8_t);
+npi_status_t npi_txc_port_dma_channel_disable(npi_handle_t, uint8_t,
+ uint8_t);
+
+npi_status_t npi_txc_pkt_stuffed_get(npi_handle_t, uint8_t,
+ uint32_t *, uint32_t *);
+npi_status_t npi_txc_pkt_xmt_to_mac_get(npi_handle_t, uint8_t,
+ uint32_t *, uint32_t *);
+npi_status_t npi_txc_reorder_get(npi_handle_t, uint8_t,
+ uint32_t *);
+npi_status_t npi_txc_dump_tdc_fzc_regs(npi_handle_t, uint8_t);
+npi_status_t npi_txc_dump_fzc_regs(npi_handle_t);
+npi_status_t npi_txc_dump_port_fzc_regs(npi_handle_t, uint8_t);
+npi_status_t npi_txc_ro_states_get(npi_handle_t, uint8_t,
+ txc_ro_states_t *);
+npi_status_t npi_txc_ro_ecc_state_clr(npi_handle_t, uint8_t);
+npi_status_t npi_txc_sf_states_get(npi_handle_t, uint8_t,
+ txc_sf_states_t *);
+npi_status_t npi_txc_sf_ecc_state_clr(npi_handle_t, uint8_t);
+void npi_txc_global_istatus_get(npi_handle_t, txc_int_stat_t *);
+void npi_txc_global_istatus_clear(npi_handle_t, uint64_t);
+void npi_txc_global_imask_set(npi_handle_t, uint8_t,
+ uint8_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_TXC_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.c b/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.c
new file mode 100644
index 0000000000..6a850bda03
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.c
@@ -0,0 +1,2057 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifdef SOLARIS
+#pragma ident "%Z%%M% %I% %E% SMI"
+#endif
+
+#include <npi_txdma.h>
+
+#define TXDMA_WAIT_LOOP 10000
+#define TXDMA_WAIT_MSEC 5
+
+static npi_status_t npi_txdma_control_reset_wait(npi_handle_t handle,
+ uint8_t channel);
+static npi_status_t npi_txdma_control_stop_wait(npi_handle_t handle,
+ uint8_t channel);
+static npi_status_t npi_txdma_control_resume_wait(npi_handle_t handle,
+ uint8_t channel);
+
+uint64_t tdc_dmc_offset[] = {
+ TX_RNG_CFIG_REG,
+ TX_RING_HDL_REG,
+ TX_RING_KICK_REG,
+ TX_ENT_MSK_REG,
+ TX_CS_REG,
+ TXDMA_MBH_REG,
+ TXDMA_MBL_REG,
+ TX_DMA_PRE_ST_REG,
+ TX_RNG_ERR_LOGH_REG,
+ TX_RNG_ERR_LOGL_REG,
+ TDMC_INTR_DBG_REG,
+ TX_CS_DBG_REG
+};
+
+const char *tdc_dmc_name[] = {
+ "TX_RNG_CFIG_REG",
+ "TX_RING_HDL_REG",
+ "TX_RING_KICK_REG",
+ "TX_ENT_MSK_REG",
+ "TX_CS_REG",
+ "TXDMA_MBH_REG",
+ "TXDMA_MBL_REG",
+ "TX_DMA_PRE_ST_REG",
+ "TX_RNG_ERR_LOGH_REG",
+ "TX_RNG_ERR_LOGL_REG",
+ "TDMC_INTR_DBG_REG",
+ "TX_CS_DBG_REG"
+};
+
+uint64_t tdc_fzc_offset [] = {
+ TX_LOG_PAGE_VLD_REG,
+ TX_LOG_PAGE_MASK1_REG,
+ TX_LOG_PAGE_VAL1_REG,
+ TX_LOG_PAGE_MASK2_REG,
+ TX_LOG_PAGE_VAL2_REG,
+ TX_LOG_PAGE_RELO1_REG,
+ TX_LOG_PAGE_RELO2_REG,
+ TX_LOG_PAGE_HDL_REG
+};
+
+const char *tdc_fzc_name [] = {
+ "TX_LOG_PAGE_VLD_REG",
+ "TX_LOG_PAGE_MASK1_REG",
+ "TX_LOG_PAGE_VAL1_REG",
+ "TX_LOG_PAGE_MASK2_REG",
+ "TX_LOG_PAGE_VAL2_REG",
+ "TX_LOG_PAGE_RELO1_REG",
+ "TX_LOG_PAGE_RELO2_REG",
+ "TX_LOG_PAGE_HDL_REG"
+};
+
+uint64_t tx_fzc_offset[] = {
+ TX_ADDR_MD_REG,
+ TDMC_INJ_PAR_ERR_REG,
+ TDMC_DBG_SEL_REG,
+ TDMC_TRAINING_REG
+};
+
+const char *tx_fzc_name[] = {
+ "TX_ADDR_MD_REG",
+ "TDMC_INJ_PAR_ERR_REG",
+ "TDMC_DBG_SEL_REG",
+ "TDMC_TRAINING_REG"
+};
+
+/*
+ * npi_txdma_dump_tdc_regs
+ * Dumps the contents of tdc csrs and fzc registers
+ *
+ * Input:
+ * tdc: TX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_TXDMA_CHANNEL_INVALID
+ *
+ */
+npi_status_t
+npi_txdma_dump_tdc_regs(npi_handle_t handle, uint8_t tdc)
+{
+
+ uint64_t value, offset;
+ int num_regs, i;
+
+ if (!TXDMA_CHANNEL_VALID(tdc)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_txdma_dump_tdc_regs"
+ " Invalid TDC number %d \n",
+ tdc));
+
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(tdc));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXDMA DMC Register Dump for Channel %d\n",
+ tdc));
+
+ num_regs = sizeof (tdc_dmc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ TXDMA_REG_READ64(handle, tdc_dmc_offset[i], tdc, &value);
+ offset = NXGE_TXDMA_OFFSET(tdc_dmc_offset[i], handle.is_vraddr,
+ tdc);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%016llx \n",
+ offset, tdc_dmc_name[i],
+ value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXDMA FZC_DMC Register Dump for Channel %d\n",
+ tdc));
+
+ num_regs = sizeof (tdc_fzc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ offset = NXGE_TXLOG_OFFSET(tdc_fzc_offset[i], tdc);
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t %016llx \n",
+ offset, tdc_fzc_name[i],
+ value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXDMA Register Dump for Channel %d done\n", tdc));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txdma_dump_fzc_regs
+ * Dumps the contents of tdc csrs and fzc registers
+ *
+ * Input:
+ * tdc: TX DMA number
+ *
+ * return:
+ * NPI_SUCCESS
+ * NPI_FAILURE
+ * NPI_TXDMA_CHANNEL_INVALID
+ *
+ */
+npi_status_t
+npi_txdma_dump_fzc_regs(npi_handle_t handle)
+{
+
+ uint64_t value;
+ int num_regs, i;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nFZC_DMC Common Register Dump\n"));
+
+ num_regs = sizeof (tx_fzc_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ NXGE_REG_RD64(handle, tx_fzc_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ tx_fzc_offset[i],
+ tx_fzc_name[i], value));
+ }
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXDMA FZC_DMC Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_tdc_regs_zero(npi_handle_t handle, uint8_t tdc)
+{
+ uint64_t value;
+ int num_regs, i;
+
+ if (!TXDMA_CHANNEL_VALID(tdc)) {
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "npi_txdma_tdc_regs_zero"
+ " InvaliInvalid TDC number %d \n",
+ tdc));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(tdc));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXDMA DMC Register (zero) for Channel %d\n",
+ tdc));
+
+ num_regs = sizeof (tdc_dmc_offset) / sizeof (uint64_t);
+ value = 0;
+ for (i = 0; i < num_regs; i++) {
+ TXDMA_REG_WRITE64(handle, tdc_dmc_offset[i], tdc,
+ value);
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nTXDMA FZC_DMC Register clear for Channel %d\n",
+ tdc));
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n TXDMA Register Clear to 0s for Channel %d done\n", tdc));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txdma_address_mode32_set():
+ * This function is called to only support 32 bit addressing.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * mode_enable - B_TRUE (enable 32 bit mode)
+ * B_FALSE (disable 32 bit mode)
+ *
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NONE
+ */
+npi_status_t
+npi_txdma_mode32_set(npi_handle_t handle, boolean_t mode_enable)
+{
+ tx_addr_md_t mode32;
+
+ mode32.value = 0;
+ if (mode_enable) {
+ mode32.bits.ldw.mode32 = 1;
+ } else {
+ mode32.bits.ldw.mode32 = 0;
+ }
+ NXGE_REG_WR64(handle, TX_ADDR_MD_REG, mode32.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txdma_log_page_set():
+ * This function is called to configure a logical page
+ * (valid bit, mask, value, relocation).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * cfgp - pointer to NPI defined data structure:
+ * - page valid
+ * - mask
+ * - value
+ * - relocation
+ * channel - hardware TXDMA channel from 0 to 23.
+ *
+ * Return:
+ * NPI_SUCCESS - If configurations are set successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_FUNC_INVALID -
+ * NPI_TXDMA_PAGE_INVALID -
+ */
+npi_status_t
+npi_txdma_log_page_set(npi_handle_t handle, uint8_t channel,
+ p_dma_log_page_t cfgp)
+{
+ log_page_vld_t vld;
+ int status;
+ uint64_t val;
+ dma_log_page_t cfg;
+
+ DMA_LOG_PAGE_FN_VALIDATE(channel, cfgp->page_num, cfgp->func_num,
+ status);
+ if (status) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_set"
+ " npi_status <0x%x>", status));
+ return (status);
+ }
+
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG, channel, 0);
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n==> npi_txdma_log_page_set: WRITE 0 and "
+ " READ back 0x%llx\n ", val));
+
+ vld.value = 0;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
+
+ val &= 0x3;
+ vld.value |= val;
+
+ vld.value = 0;
+ vld.bits.ldw.func = cfgp->func_num;
+
+ if (!cfgp->page_num) {
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_MASK1_REG,
+ channel, (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VAL1_REG,
+ channel, (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_RELO1_REG,
+ channel, (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
+ } else {
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_MASK2_REG,
+ channel, (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VAL2_REG,
+ channel, (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_RELO2_REG,
+ channel, (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
+ }
+
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG, channel,
+ vld.value | (cfgp->valid << cfgp->page_num));
+
+ NPI_DEBUG_MSG((handle.function, NPI_REG_CTL,
+ "\n==> npi_txdma_log_page_set: vld value "
+ " 0x%llx function %d page_valid01 0x%x\n",
+ vld.value,
+ vld.bits.ldw.func,
+ (cfgp->valid << cfgp->page_num)));
+
+
+ cfg.page_num = 0;
+ cfg.func_num = 0;
+ (void) npi_txdma_log_page_get(handle, channel, &cfg);
+ cfg.page_num = 1;
+ (void) npi_txdma_log_page_get(handle, channel, &cfg);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_log_page_get():
+ * This function is called to get a logical page
+ * (valid bit, mask, value, relocation).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * cfgp - Get the following values (NPI defined structure):
+ * - page valid
+ * - mask
+ * - value
+ * - relocation
+ * channel - hardware TXDMA channel from 0 to 23.
+ *
+ * Return:
+ * NPI_SUCCESS - If configurations are read successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_FUNC_INVALID -
+ * NPI_TXDMA_PAGE_INVALID -
+ */
+npi_status_t
+npi_txdma_log_page_get(npi_handle_t handle, uint8_t channel,
+ p_dma_log_page_t cfgp)
+{
+ log_page_vld_t vld;
+ int status;
+ uint64_t val;
+
+ DMA_LOG_PAGE_VALIDATE(channel, cfgp->page_num, status);
+ if (status) {
+ NPI_ERROR_MSG((handle.function, NPI_REG_CTL,
+ " npi_txdma_log_page_get"
+ " npi_status <0x%x>", status));
+ return (status);
+ }
+
+ vld.value = 0;
+ vld.bits.ldw.func = cfgp->func_num;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n==> npi_txdma_log_page_get: read value "
+ " function %d value 0x%llx\n",
+ cfgp->func_num, val));
+
+ vld.value |= val;
+ cfgp->func_num = vld.bits.ldw.func;
+
+ if (!cfgp->page_num) {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK1_REG, channel, &val);
+ cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL1_REG, channel, &val);
+ cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO1_REG, channel, &val);
+ cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
+ cfgp->valid = vld.bits.ldw.page0;
+ } else {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK2_REG, channel, &val);
+ cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG, channel, &val);
+ cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO2_REG, channel, &val);
+ cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
+ cfgp->valid = vld.bits.ldw.page1;
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_log_page_handle_set():
+ * This function is called to program a page handle
+ * (bits [63:44] of a 64-bit address to generate
+ * a 64 bit address)
+ *
+ * Parameters:
+ * handle - NPI handle
+ * hdl_p - pointer to a logical page handle
+ * hardware data structure (log_page_hdl_t).
+ * channel - hardware TXDMA channel from 0 to 23.
+ *
+ * Return:
+ * NPI_SUCCESS - If configurations are set successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_FUNC_INVALID -
+ * NPI_TXDMA_PAGE_INVALID -
+ */
+npi_status_t
+npi_txdma_log_page_handle_set(npi_handle_t handle, uint8_t channel,
+ p_log_page_hdl_t hdl_p)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_handle_set"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_HDL_REG,
+ channel, hdl_p->value);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_log_page_config():
+ * This function is called to IO operations on
+ * a logical page to set, get, clear
+ * valid bit, mask, value, relocation).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET, OP_SET, OP_CLEAR
+ * type - NPI specific config type
+ * TXDMA_LOG_PAGE_MASK
+ * TXDMA_LOG_PAGE_VALUE
+ * TXDMA_LOG_PAGE_RELOC
+ * TXDMA_LOG_PAGE_VALID
+ * TXDMA_LOG_PAGE_ALL
+ * channel - hardware TXDMA channel from 0 to 23.
+ * cfgp - pointer to the NPI config structure.
+ * Return:
+ * NPI_SUCCESS - If configurations are read successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_FUNC_INVALID -
+ * NPI_TXDMA_PAGE_INVALID -
+ */
+npi_status_t
+npi_txdma_log_page_config(npi_handle_t handle, io_op_t op_mode,
+ txdma_log_cfg_t type, uint8_t channel,
+ p_dma_log_page_t cfgp)
+{
+ int status = NPI_SUCCESS;
+ uint64_t val;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_config"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ switch (type) {
+ case TXDMA_LOG_PAGE_ALL:
+ return (npi_txdma_log_page_get(handle, channel,
+ cfgp));
+ case TXDMA_LOG_PAGE_MASK:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK1_REG,
+ channel, &val);
+ cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
+ } else {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK2_REG,
+ channel, &val);
+ cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
+ }
+ break;
+
+ case TXDMA_LOG_PAGE_VALUE:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL1_REG,
+ channel, &val);
+ cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
+ } else {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG,
+ channel, &val);
+ cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
+ }
+ break;
+
+ case TXDMA_LOG_PAGE_RELOC:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO1_REG,
+ channel, &val);
+ cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
+ } else {
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG,
+ channel, &val);
+ cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
+ }
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_config"
+ " Invalid Input: pageconfig <0x%x>",
+ type));
+ return (NPI_FAILURE |
+ NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ break;
+
+ case OP_SET:
+ case OP_CLEAR:
+ if (op_mode == OP_CLEAR) {
+ cfgp->valid = 0;
+ cfgp->mask = cfgp->func_num = 0;
+ cfgp->value = cfgp->reloc = 0;
+ }
+ switch (type) {
+ case TXDMA_LOG_PAGE_ALL:
+ return (npi_txdma_log_page_set(handle, channel,
+ cfgp));
+ case TXDMA_LOG_PAGE_MASK:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_MASK1_REG, channel,
+ (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
+ } else {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_MASK2_REG,
+ channel, (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
+ }
+ break;
+
+ case TXDMA_LOG_PAGE_VALUE:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_VAL1_REG, channel,
+ (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
+ } else {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_VAL2_REG, channel,
+ (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
+ }
+ break;
+
+ case TXDMA_LOG_PAGE_RELOC:
+ if (!cfgp->page_num) {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_RELO1_REG, channel,
+ (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
+ } else {
+ TX_LOG_REG_WRITE64(handle,
+ TX_LOG_PAGE_RELO2_REG, channel,
+ (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
+ }
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_config"
+ " Invalid Input: pageconfig <0x%x>",
+ type));
+ return (NPI_FAILURE |
+ NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_config"
+ " Invalid Input: op <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_log_page_vld_config():
+ * This function is called to configure the logical
+ * page valid register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get valid page configuration
+ * OP_SET: set valid page configuration
+ * OP_UPDATE: update valid page configuration
+ * OP_CLEAR: reset both valid pages to
+ * not defined (0).
+ * channel - hardware TXDMA channel from 0 to 23.
+ * vld_p - pointer to hardware defined log page valid register.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_OPCODE_INVALID -
+ */
+npi_status_t
+npi_txdma_log_page_vld_config(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, p_log_page_vld_t vld_p)
+{
+ int status = NPI_SUCCESS;
+ log_page_vld_t vld;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_page_vld_config"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel,
+ &vld_p->value);
+ break;
+
+ case OP_SET:
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
+ channel, vld_p->value);
+ break;
+
+ case OP_UPDATE:
+ TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel,
+ &vld.value);
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
+ channel, vld.value | vld_p->value);
+ break;
+
+ case OP_CLEAR:
+ TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
+ channel, 0);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_log_pag_vld_cofig"
+ " Invalid Input: pagevld <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_channel_reset():
+ * This function is called to reset a transmit DMA channel.
+ * (This function is used to reset a channel and reinitialize
+ * all other bits except RST_STATE).
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ *
+ * Return:
+ * NPI_SUCCESS - If reset is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_RESET_FAILED -
+ */
+npi_status_t
+npi_txdma_channel_reset(npi_handle_t handle, uint8_t channel)
+{
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ " npi_txdma_channel_reset"
+ " RESETTING",
+ channel));
+ return (npi_txdma_channel_control(handle, TXDMA_RESET, channel));
+}
+
+/*
+ * npi_txdma_channel_init_enable():
+ * This function is called to start a transmit DMA channel after reset.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If DMA channel is started successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_channel_init_enable(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_INIT_START, channel));
+}
+
+/*
+ * npi_txdma_channel_enable():
+ * This function is called to start a transmit DMA channel.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If DMA channel is stopped successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+
+npi_status_t
+npi_txdma_channel_enable(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_START, channel));
+}
+
+/*
+ * npi_txdma_channel_disable():
+ * This function is called to stop a transmit DMA channel.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If DMA channel is stopped successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_STOP_FAILED -
+ */
+npi_status_t
+npi_txdma_channel_disable(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_STOP, channel));
+}
+
+/*
+ * npi_txdma_channel_resume():
+ * This function is called to restart a transmit DMA channel.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If DMA channel is stopped successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_RESUME_FAILED -
+ */
+npi_status_t
+npi_txdma_channel_resume(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_RESUME, channel));
+}
+
+/*
+ * npi_txdma_channel_mmk_clear():
+ * This function is called to clear MMK bit.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If MMK is reset successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_channel_mmk_clear(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_CLEAR_MMK, channel));
+}
+
+/*
+ * npi_txdma_channel_mbox_enable():
+ * This function is called to enable the mailbox update.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * Return:
+ * NPI_SUCCESS - If mailbox is enabled successfully.
+ *
+ * Error:
+ * NPI_HW_ERROR -
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_channel_mbox_enable(npi_handle_t handle, uint8_t channel)
+{
+ return (npi_txdma_channel_control(handle, TXDMA_MBOX_ENABLE, channel));
+}
+
+/*
+ * npi_txdma_channel_control():
+ * This function is called to control a transmit DMA channel
+ * for reset, start or stop.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * control - NPI defined control type supported
+ * - TXDMA_INIT_RESET
+ * - TXDMA_INIT_START
+ * - TXDMA_RESET
+ * - TXDMA_START
+ * - TXDMA_STOP
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ *
+ * Return:
+ * NPI_SUCCESS - If reset is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_RESET_FAILED -
+ * NPI_TXDMA_STOP_FAILED -
+ * NPI_TXDMA_RESUME_FAILED -
+ */
+npi_status_t
+npi_txdma_channel_control(npi_handle_t handle, txdma_cs_cntl_t control,
+ uint8_t channel)
+{
+ int status = NPI_SUCCESS;
+ tx_cs_t cs;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_channel_control"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (control) {
+ case TXDMA_INIT_RESET:
+ cs.value = 0;
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.bits.ldw.rst = 1;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ return (npi_txdma_control_reset_wait(handle, channel));
+
+ case TXDMA_INIT_START:
+ cs.value = 0;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ break;
+
+ case TXDMA_RESET:
+ /*
+ * Sets reset bit only (Hardware will reset all
+ * the RW bits but leave the RO bits alone.
+ */
+ cs.value = 0;
+ cs.bits.ldw.rst = 1;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ return (npi_txdma_control_reset_wait(handle, channel));
+
+ case TXDMA_START:
+ /* Enable the DMA channel */
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.bits.ldw.stop_n_go = 0;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ break;
+
+ case TXDMA_STOP:
+ /* Disable the DMA channel */
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.bits.ldw.stop_n_go = 1;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ status = npi_txdma_control_stop_wait(handle, channel);
+ if (status) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "Cannot stop channel %d (TXC hung!)",
+ channel));
+ }
+ break;
+
+ case TXDMA_RESUME:
+ /* Resume the packet transmission after stopping */
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.value |= ~TX_CS_STOP_N_GO_MASK;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ return (npi_txdma_control_resume_wait(handle, channel));
+
+ case TXDMA_CLEAR_MMK:
+ /* Write 1 to MK bit to clear the MMK bit */
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.bits.ldw.mk = 1;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ break;
+
+ case TXDMA_MBOX_ENABLE:
+ /*
+ * Write 1 to MB bit to enable mailbox update
+ * (cleared to 0 by hardware after update).
+ */
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
+ cs.bits.ldw.mb = 1;
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
+ break;
+
+ default:
+ status = (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_channel_control"
+ " Invalid Input: control <0x%x>",
+ control));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_control_status():
+ * This function is called to operate on the control
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware control and status
+ * OP_SET: set hardware control and status
+ * OP_UPDATE: update hardware control and status.
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware TXDMA channel from 0 to 23.
+ * cs_p - pointer to hardware defined control and status
+ * structure.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_FUNC_INVALID -
+ */
+npi_status_t
+npi_txdma_control_status(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, p_tx_cs_t cs_p)
+{
+ int status = NPI_SUCCESS;
+ tx_cs_t txcs;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_control_status"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs_p->value);
+ break;
+
+ case OP_SET:
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs_p->value);
+ break;
+
+ case OP_UPDATE:
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
+ TXDMA_REG_WRITE64(handle, TX_CS_REG, channel,
+ cs_p->value | txcs.value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_control_status"
+ " Invalid Input: control <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+
+}
+
+/*
+ * npi_txdma_event_mask():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts..
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware TXDMA channel from 0 to 23.
+ * mask_p - pointer to hardware defined event mask
+ * structure.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_event_mask(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, p_tx_dma_ent_msk_t mask_p)
+{
+ int status = NPI_SUCCESS;
+ tx_dma_ent_msk_t mask;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel,
+ &mask_p->value);
+ break;
+
+ case OP_SET:
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ mask_p->value);
+ break;
+
+ case OP_UPDATE:
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &mask.value);
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ mask_p->value | mask.value);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask"
+ " Invalid Input: eventmask <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_event_mask_config():
+ * This function is called to operate on the event mask
+ * register which is used for generating interrupts..
+ * and status register.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * op_mode - OP_GET: get hardware event mask
+ * OP_SET: set hardware interrupt event masks
+ * OP_CLEAR: clear control and status register to 0s.
+ * channel - hardware TXDMA channel from 0 to 23.
+ * cfgp - pointer to NPI defined event mask
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_event_mask_config(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, txdma_ent_msk_cfg_t *mask_cfgp)
+{
+ int status = NPI_SUCCESS;
+ uint64_t value;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask_config"
+ " Invalid Input: channel <0x%x>",
+ channel));
+
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, mask_cfgp);
+ break;
+
+ case OP_SET:
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ *mask_cfgp);
+ break;
+
+ case OP_UPDATE:
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &value);
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ *mask_cfgp | value);
+ break;
+
+ case OP_CLEAR:
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ CFG_TXDMA_MASK_ALL);
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask_config"
+ " Invalid Input: eventmask <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_event_mask_mk_out():
+ * This function is called to mask out the packet transmit marked event.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * channel - hardware TXDMA channel from 0 to 23.
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_event_mask_mk_out(npi_handle_t handle, uint8_t channel)
+{
+ txdma_ent_msk_cfg_t event_mask;
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask_mk_out"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &event_mask);
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ event_mask & (~TX_ENT_MSK_MK_MASK));
+
+ return (status);
+}
+
+/*
+ * npi_txdma_event_mask_mk_in():
+ * This function is called to set the mask for the the packet marked event.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * channel - hardware TXDMA channel from 0 to 23.
+ * enum data type.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_event_mask_mk_in(npi_handle_t handle, uint8_t channel)
+{
+ txdma_ent_msk_cfg_t event_mask;
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_event_mask_mk_in"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &event_mask);
+ TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
+ event_mask | TX_ENT_MSK_MK_MASK);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_ring_addr_set():
+ * This function is called to configure the transmit descriptor
+ * ring address and its size.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined
+ * if its register pointer is from the virtual region).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * start_addr - starting address of the descriptor
+ * len - maximum length of the descriptor
+ * (in number of 64 bytes block).
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_ring_addr_set(npi_handle_t handle, uint8_t channel,
+ uint64_t start_addr, uint32_t len)
+{
+ int status = NPI_SUCCESS;
+ tx_rng_cfig_t cfg;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_ring_addr_set"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ cfg.value = ((start_addr & TX_RNG_CFIG_ADDR_MASK) |
+ (((uint64_t)len) << TX_RNG_CFIG_LEN_SHIFT));
+ TXDMA_REG_WRITE64(handle, TX_RNG_CFIG_REG, channel, cfg.value);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_ring_config():
+ * This function is called to config a descriptor ring
+ * by using the hardware defined data.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined
+ * if its register pointer is from the virtual region).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * op_mode - OP_GET: get transmit ring configuration
+ * OP_SET: set transmit ring configuration
+ * reg_data - pointer to hardware defined transmit ring
+ * configuration data structure.
+ * Return:
+ * NPI_SUCCESS - If set/get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_ring_config(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, uint64_t *reg_data)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_ring_config"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ switch (op_mode) {
+ case OP_GET:
+ TXDMA_REG_READ64(handle, TX_RNG_CFIG_REG, channel, reg_data);
+ break;
+
+ case OP_SET:
+ TXDMA_REG_WRITE64(handle, TX_RNG_CFIG_REG, channel,
+ *reg_data);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_ring_config"
+ " Invalid Input: ring_config <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+}
+
+/*
+ * npi_txdma_mbox_config():
+ * This function is called to config the mailbox address
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined
+ * if its register pointer is from the virtual region).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * op_mode - OP_GET: get the mailbox address
+ * OP_SET: set the mailbox address
+ * reg_data - pointer to the mailbox address.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_mbox_config(npi_handle_t handle, io_op_t op_mode,
+ uint8_t channel, uint64_t *mbox_addr)
+{
+ int status = NPI_SUCCESS;
+ txdma_mbh_t mh;
+ txdma_mbl_t ml;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_mbox_config"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ mh.value = ml.value = 0;
+
+ switch (op_mode) {
+ case OP_GET:
+ TXDMA_REG_READ64(handle, TXDMA_MBH_REG, channel, &mh.value);
+ TXDMA_REG_READ64(handle, TXDMA_MBL_REG, channel, &ml.value);
+ *mbox_addr = ml.value;
+ *mbox_addr |= (mh.value << TXDMA_MBH_ADDR_SHIFT);
+
+ break;
+
+ case OP_SET:
+ ml.bits.ldw.mbaddr = ((*mbox_addr & TXDMA_MBL_MASK) >>
+ TXDMA_MBL_SHIFT);
+ TXDMA_REG_WRITE64(handle, TXDMA_MBL_REG, channel, ml.value);
+ mh.bits.ldw.mbaddr = ((*mbox_addr >> TXDMA_MBH_ADDR_SHIFT) &
+ TXDMA_MBH_MASK);
+ TXDMA_REG_WRITE64(handle, TXDMA_MBH_REG, channel, mh.value);
+
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_mbox_config"
+ " Invalid Input: mbox <0x%x>",
+ op_mode));
+ return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
+ }
+
+ return (status);
+
+}
+
+/*
+ * npi_txdma_desc_gather_set():
+ * This function is called to set up a transmit descriptor entry.
+ *
+ * Parameters:
+ * handle - NPI handle (register pointer is the
+ * descriptor address in memory).
+ * desc_p - pointer to a descriptor
+ * gather_index - which entry (starts from index 0 to 15)
+ * mark - mark bit (only valid if it is the first gather).
+ * ngathers - number of gather pointers to set to the first gather.
+ * dma_ioaddr - starting dma address of an IO buffer to write.
+ * (SAD)
+ * transfer_len - transfer len.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_OPCODE_INVALID -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ * NPI_TXDMA_XFER_LEN_INVALID -
+ */
+npi_status_t
+npi_txdma_desc_gather_set(npi_handle_t handle,
+ p_tx_desc_t desc_p, uint8_t gather_index,
+ boolean_t mark, uint8_t ngathers,
+ uint64_t dma_ioaddr, uint32_t transfer_len)
+{
+ int status;
+
+ status = NPI_TXDMA_GATHER_INDEX(gather_index);
+ if (status) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_desc_gather_set"
+ " Invalid Input: gather_index <0x%x>",
+ gather_index));
+ return (status);
+ }
+
+ if (transfer_len > TX_MAX_TRANSFER_LENGTH) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_desc_gather_set"
+ " Invalid Input: tr_len <0x%x>",
+ transfer_len));
+ return (NPI_FAILURE | NPI_TXDMA_XFER_LEN_INVALID);
+ }
+
+ if (gather_index == 0) {
+ desc_p->bits.hdw.sop = 1;
+ desc_p->bits.hdw.mark = mark;
+ desc_p->bits.hdw.num_ptr = ngathers;
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "npi_txdma_gather_set: SOP len %d (%d)",
+ desc_p->bits.hdw.tr_len, transfer_len));
+ }
+
+ desc_p->bits.hdw.tr_len = transfer_len;
+ desc_p->bits.hdw.sad = dma_ioaddr >> 32;
+ desc_p->bits.ldw.sad = dma_ioaddr & 0xffffffff;
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "npi_txdma_gather_set: xfer len %d to set (%d)",
+ desc_p->bits.hdw.tr_len, transfer_len));
+
+ NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_desc_sop_set():
+ * This function is called to set up the first gather entry.
+ *
+ * Parameters:
+ * handle - NPI handle (register pointer is the
+ * descriptor address in memory).
+ * desc_p - pointer to a descriptor
+ * mark - mark bit (only valid if it is the first gather).
+ * ngathers - number of gather pointers to set to the first gather.
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_txdma_desc_gather_sop_set(npi_handle_t handle,
+ p_tx_desc_t desc_p,
+ boolean_t mark_mode,
+ uint8_t ngathers)
+{
+ int status = NPI_SUCCESS;
+
+ desc_p->bits.hdw.sop = 1;
+ desc_p->bits.hdw.mark = mark_mode;
+ desc_p->bits.hdw.num_ptr = ngathers;
+
+ NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
+
+ return (status);
+}
+npi_status_t
+npi_txdma_desc_gather_sop_set_1(npi_handle_t handle,
+ p_tx_desc_t desc_p,
+ boolean_t mark_mode,
+ uint8_t ngathers,
+ uint32_t extra)
+{
+ int status = NPI_SUCCESS;
+
+ desc_p->bits.hdw.sop = 1;
+ desc_p->bits.hdw.mark = mark_mode;
+ desc_p->bits.hdw.num_ptr = ngathers;
+ desc_p->bits.hdw.tr_len += extra;
+
+ NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
+
+ return (status);
+}
+
+npi_status_t
+npi_txdma_desc_set_xfer_len(npi_handle_t handle,
+ p_tx_desc_t desc_p,
+ uint32_t transfer_len)
+{
+ int status = NPI_SUCCESS;
+
+ desc_p->bits.hdw.tr_len = transfer_len;
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "npi_set_xfer_len: len %d (%d)",
+ desc_p->bits.hdw.tr_len, transfer_len));
+
+ NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
+
+ return (status);
+}
+
+npi_status_t
+npi_txdma_desc_set_zero(npi_handle_t handle, uint16_t entries)
+{
+ uint32_t offset;
+ int i;
+
+ /*
+ * Assume no wrapped around.
+ */
+ offset = 0;
+ for (i = 0; i < entries; i++) {
+ NXGE_REG_WR64(handle, offset, 0);
+ offset += (i * TXDMA_DESC_SIZE);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_txdma_desc_mem_get(npi_handle_t handle, uint16_t index,
+ p_tx_desc_t desc_p)
+{
+ int status = NPI_SUCCESS;
+
+ npi_txdma_dump_desc_one(handle, desc_p, index);
+
+ return (status);
+
+}
+
+/*
+ * npi_txdma_desc_kick_reg_set():
+ * This function is called to kick the transmit to start transmission.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * tail_index - index into the transmit descriptor
+ * wrap - toggle bit to indicate if the tail index is
+ * wrapped around.
+ *
+ * Return:
+ * NPI_SUCCESS - If set is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_desc_kick_reg_set(npi_handle_t handle, uint8_t channel,
+ uint16_t tail_index, boolean_t wrap)
+{
+ int status = NPI_SUCCESS;
+ tx_ring_kick_t kick;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_desc_kick_reg_set"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ " npi_txdma_desc_kick_reg_set: "
+ " KICKING channel %d",
+ channel));
+
+ /* Toggle the wrap around bit */
+ kick.value = 0;
+ kick.bits.ldw.wrap = wrap;
+ kick.bits.ldw.tail = tail_index;
+
+ /* Kick start the Transmit kick register */
+ TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, kick.value);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_desc_kick_reg_get():
+ * This function is called to kick the transmit to start transmission.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * tail_index - index into the transmit descriptor
+ * wrap - toggle bit to indicate if the tail index is
+ * wrapped around.
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_desc_kick_reg_get(npi_handle_t handle, uint8_t channel,
+ p_tx_ring_kick_t kick_p)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_desc_kick_reg_get"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_READ64(handle, TX_RING_KICK_REG, channel, &kick_p->value);
+
+ return (status);
+}
+
+/*
+ * npi_txdma_ring_head_get():
+ * This function is called to get the transmit ring head index.
+ *
+ * Parameters:
+ * handle - NPI handle (virtualization flag must be defined).
+ * channel - logical TXDMA channel from 0 to 23.
+ * (If virtualization flag is not set, then
+ * logical channel is the same as the hardware
+ * channel number).
+ * hdl_p - pointer to the hardware defined transmit
+ * ring header data (head index and wrap bit).
+ *
+ * Return:
+ * NPI_SUCCESS - If get is complete successfully.
+ *
+ * Error:
+ * NPI_FAILURE -
+ * NPI_TXDMA_CHANNEL_INVALID -
+ */
+npi_status_t
+npi_txdma_ring_head_get(npi_handle_t handle, uint8_t channel,
+ p_tx_ring_hdl_t hdl_p)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_ring_head_get"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_READ64(handle, TX_RING_HDL_REG, channel, &hdl_p->value);
+
+ return (status);
+}
+
+/*ARGSUSED*/
+npi_status_t
+npi_txdma_channel_mbox_get(npi_handle_t handle, uint8_t channel,
+ p_txdma_mailbox_t mbox_p)
+{
+ int status = NPI_SUCCESS;
+
+ return (status);
+
+}
+
+npi_status_t
+npi_txdma_channel_pre_state_get(npi_handle_t handle, uint8_t channel,
+ p_tx_dma_pre_st_t prep)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_channel_pre_state_get"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_READ64(handle, TX_DMA_PRE_ST_REG, channel, &prep->value);
+
+ return (status);
+}
+
+npi_status_t
+npi_txdma_ring_error_get(npi_handle_t handle, uint8_t channel,
+ p_txdma_ring_errlog_t ring_errlog_p)
+{
+ tx_rng_err_logh_t logh;
+ tx_rng_err_logl_t logl;
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_ring_error_get"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ logh.value = 0;
+ TXDMA_REG_READ64(handle, TX_RNG_ERR_LOGH_REG, channel, &logh.value);
+ TXDMA_REG_READ64(handle, TX_RNG_ERR_LOGL_REG, channel, &logl.value);
+ ring_errlog_p->logh.bits.ldw.err = logh.bits.ldw.err;
+ ring_errlog_p->logh.bits.ldw.merr = logh.bits.ldw.merr;
+ ring_errlog_p->logh.bits.ldw.errcode = logh.bits.ldw.errcode;
+ ring_errlog_p->logh.bits.ldw.err_addr = logh.bits.ldw.err_addr;
+ ring_errlog_p->logl.bits.ldw.err_addr = logl.bits.ldw.err_addr;
+
+ return (status);
+}
+
+npi_status_t
+npi_txdma_inj_par_error_clear(npi_handle_t handle)
+{
+ NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, 0);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_inj_par_error_set(npi_handle_t handle, uint32_t err_bits)
+{
+ tdmc_inj_par_err_t inj;
+
+ inj.value = 0;
+ inj.bits.ldw.inject_parity_error = (err_bits & TDMC_INJ_PAR_ERR_MASK);
+ NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, inj.value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_inj_par_error_update(npi_handle_t handle, uint32_t err_bits)
+{
+ tdmc_inj_par_err_t inj;
+
+ inj.value = 0;
+ NXGE_REG_RD64(handle, TDMC_INJ_PAR_ERR_REG, &inj.value);
+ inj.value |= (err_bits & TDMC_INJ_PAR_ERR_MASK);
+ NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, inj.value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_inj_par_error_get(npi_handle_t handle, uint32_t *err_bits)
+{
+ tdmc_inj_par_err_t inj;
+
+ inj.value = 0;
+ NXGE_REG_RD64(handle, TDMC_INJ_PAR_ERR_REG, &inj.value);
+ *err_bits = (inj.value & TDMC_INJ_PAR_ERR_MASK);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_dbg_sel_set(npi_handle_t handle, uint8_t dbg_sel)
+{
+ tdmc_dbg_sel_t dbg;
+
+ dbg.value = 0;
+ dbg.bits.ldw.dbg_sel = (dbg_sel & TDMC_DBG_SEL_MASK);
+
+ NXGE_REG_WR64(handle, TDMC_DBG_SEL_REG, dbg.value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_txdma_training_vector_set(npi_handle_t handle, uint32_t training_vector)
+{
+ tdmc_training_t vec;
+
+ vec.value = 0;
+ vec.bits.ldw.vec = training_vector;
+
+ NXGE_REG_WR64(handle, TDMC_TRAINING_REG, vec.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_txdma_dump_desc_one(npi_handle_t handle, p_tx_desc_t desc_p,
+ * int desc_index)
+ *
+ * Dumps the contents of transmit descriptors.
+ *
+ * Parameters:
+ * handle - NPI handle (register pointer is the
+ * descriptor address in memory).
+ * desc_p - pointer to place the descriptor contents
+ * desc_index - descriptor index
+ *
+ */
+/*ARGSUSED*/
+void
+npi_txdma_dump_desc_one(npi_handle_t handle, p_tx_desc_t desc_p, int desc_index)
+{
+
+ tx_desc_t desc, *desp;
+#ifdef NXGE_DEBUG
+ uint64_t sad;
+ int xfer_len;
+#endif
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n==> npi_txdma_dump_desc_one: dump "
+ " desc_p $%p descriptor entry %d\n",
+ desc_p, desc_index));
+ desc.value = 0;
+ desp = ((desc_p != NULL) ? desc_p : (p_tx_desc_t)&desc);
+ desp->value = NXGE_MEM_PIO_READ64(handle);
+#ifdef NXGE_DEBUG
+ sad = (desp->value & TX_PKT_DESC_SAD_MASK);
+ xfer_len = ((desp->value & TX_PKT_DESC_TR_LEN_MASK) >>
+ TX_PKT_DESC_TR_LEN_SHIFT);
+#endif
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL, "\n\t: value 0x%llx\n"
+ "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n",
+ desp->value,
+ sad,
+ desp->bits.hdw.tr_len,
+ xfer_len,
+ desp->bits.hdw.num_ptr,
+ desp->bits.hdw.mark,
+ desp->bits.hdw.sop));
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n<== npi_txdma_dump_desc_one: Done \n"));
+
+}
+
+/*ARGSUSED*/
+void
+npi_txdma_dump_hdr(npi_handle_t handle, p_tx_pkt_header_t hdrp)
+{
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n==> npi_txdma_dump_hdr: dump\n"));
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n\t: value 0x%llx\n"
+ "\t\tpkttype 0x%x\tip_ver %d\tllc %d\tvlan %d \tihl %d\n"
+ "\t\tl3start %d\tl4start %d\tl4stuff %d\n"
+ "\t\txferlen %d\tpad %d\n",
+ hdrp->value,
+ hdrp->bits.hdw.cksum_en_pkt_type,
+ hdrp->bits.hdw.ip_ver,
+ hdrp->bits.hdw.llc,
+ hdrp->bits.hdw.vlan,
+ hdrp->bits.hdw.ihl,
+ hdrp->bits.hdw.l3start,
+ hdrp->bits.hdw.l4start,
+ hdrp->bits.hdw.l4stuff,
+ hdrp->bits.ldw.tot_xfer_len,
+ hdrp->bits.ldw.pad));
+
+ NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
+ "\n<== npi_txdma_dump_hdr: Done \n"));
+}
+
+npi_status_t
+npi_txdma_inj_int_error_set(npi_handle_t handle, uint8_t channel,
+ p_tdmc_intr_dbg_t erp)
+{
+ int status = NPI_SUCCESS;
+
+ if (!TXDMA_CHANNEL_VALID(channel)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_txdma_inj_int_error_set"
+ " Invalid Input: channel <0x%x>",
+ channel));
+ return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
+ }
+
+ TXDMA_REG_WRITE64(handle, TDMC_INTR_DBG_REG, channel, erp->value);
+
+ return (status);
+}
+
+/*
+ * Static functions start here.
+ */
+static npi_status_t
+npi_txdma_control_reset_wait(npi_handle_t handle, uint8_t channel)
+{
+
+ tx_cs_t txcs;
+ int loop = 0;
+
+ do {
+ NXGE_DELAY(TXDMA_WAIT_MSEC);
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
+ if (!txcs.bits.ldw.rst) {
+ return (NPI_SUCCESS);
+ }
+ loop++;
+ } while (loop < TXDMA_WAIT_LOOP);
+
+ if (loop == TXDMA_WAIT_LOOP) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_txdma_control_reset_wait: RST bit not "
+ "cleared to 0 txcs.bits 0x%llx", txcs.value));
+ return (NPI_FAILURE | NPI_TXDMA_RESET_FAILED);
+ }
+ return (NPI_SUCCESS);
+}
+
+static npi_status_t
+npi_txdma_control_stop_wait(npi_handle_t handle, uint8_t channel)
+{
+ tx_cs_t txcs;
+ int loop = 0;
+
+ do {
+ NXGE_DELAY(TXDMA_WAIT_MSEC);
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
+ if (txcs.bits.ldw.sng_state) {
+ return (NPI_SUCCESS);
+ }
+ loop++;
+ } while (loop < TXDMA_WAIT_LOOP);
+
+ if (loop == TXDMA_WAIT_LOOP) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_txdma_control_stop_wait: SNG_STATE not "
+ "set to 1 txcs.bits 0x%llx", txcs.value));
+ return (NPI_FAILURE | NPI_TXDMA_STOP_FAILED);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+static npi_status_t
+npi_txdma_control_resume_wait(npi_handle_t handle, uint8_t channel)
+{
+ tx_cs_t txcs;
+ int loop = 0;
+
+ do {
+ NXGE_DELAY(TXDMA_WAIT_MSEC);
+ TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
+ if (!txcs.bits.ldw.sng_state) {
+ return (NPI_SUCCESS);
+ }
+ loop++;
+ } while (loop < TXDMA_WAIT_LOOP);
+
+ if (loop == TXDMA_WAIT_LOOP) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "npi_txdma_control_resume_wait: sng_state not "
+ "set to 0 txcs.bits 0x%llx", txcs.value));
+ return (NPI_FAILURE | NPI_TXDMA_RESUME_FAILED);
+ }
+
+ return (NPI_SUCCESS);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.h b/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.h
new file mode 100644
index 0000000000..fe694ab3d1
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_txdma.h
@@ -0,0 +1,290 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_TXDMA_H
+#define _NPI_TXDMA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_txdma_hw.h>
+
+#define DMA_LOG_PAGE_FN_VALIDATE(cn, pn, fn, status) \
+{ \
+ status = NPI_SUCCESS; \
+ if (!TXDMA_CHANNEL_VALID(channel)) { \
+ status = (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(cn)); \
+ } else if (!TXDMA_PAGE_VALID(pn)) { \
+ status = (NPI_FAILURE | NPI_TXDMA_PAGE_INVALID(pn)); \
+ } else if (!TXDMA_FUNC_VALID(fn)) { \
+ status = (NPI_FAILURE | NPI_TXDMA_FUNC_INVALID(fn)); \
+ } \
+}
+
+#define DMA_LOG_PAGE_VALIDATE(cn, pn, status) \
+{ \
+ status = NPI_SUCCESS; \
+ if (!TXDMA_CHANNEL_VALID(channel)) { \
+ status = (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(cn)); \
+ } else if (!TXDMA_PAGE_VALID(pn)) { \
+ status = (NPI_FAILURE | NPI_TXDMA_PAGE_INVALID(pn)); \
+ } \
+}
+
+typedef enum _txdma_cs_cntl_e {
+ TXDMA_INIT_RESET = 0x1,
+ TXDMA_INIT_START = 0x2,
+ TXDMA_START = 0x3,
+ TXDMA_RESET = 0x4,
+ TXDMA_STOP = 0x5,
+ TXDMA_RESUME = 0x6,
+ TXDMA_CLEAR_MMK = 0x7,
+ TXDMA_MBOX_ENABLE = 0x8
+} txdma_cs_cntl_t;
+
+typedef enum _txdma_log_cfg_e {
+ TXDMA_LOG_PAGE_MASK = 0x01,
+ TXDMA_LOG_PAGE_VALUE = 0x02,
+ TXDMA_LOG_PAGE_RELOC = 0x04,
+ TXDMA_LOG_PAGE_VALID = 0x08,
+ TXDMA_LOG_PAGE_ALL = (TXDMA_LOG_PAGE_MASK | TXDMA_LOG_PAGE_VALUE |
+ TXDMA_LOG_PAGE_RELOC | TXDMA_LOG_PAGE_VALID)
+} txdma_log_cfg_t;
+
+typedef enum _txdma_ent_msk_cfg_e {
+ CFG_TXDMA_PKT_PRT_MASK = TX_ENT_MSK_PKT_PRT_ERR_MASK,
+ CFG_TXDMA_CONF_PART_MASK = TX_ENT_MSK_CONF_PART_ERR_MASK,
+ CFG_TXDMA_NACK_PKT_RD_MASK = TX_ENT_MSK_NACK_PKT_RD_MASK,
+ CFG_TXDMA_NACK_PREF_MASK = TX_ENT_MSK_NACK_PREF_MASK,
+ CFG_TXDMA_PREF_BUF_ECC_ERR_MASK = TX_ENT_MSK_PREF_BUF_ECC_ERR_MASK,
+ CFG_TXDMA_TX_RING_OFLOW_MASK = TX_ENT_MSK_TX_RING_OFLOW_MASK,
+ CFG_TXDMA_PKT_SIZE_ERR_MASK = TX_ENT_MSK_PKT_SIZE_ERR_MASK,
+ CFG_TXDMA_MBOX_ERR_MASK = TX_ENT_MSK_MBOX_ERR_MASK,
+ CFG_TXDMA_MK_MASK = TX_ENT_MSK_MK_MASK,
+ CFG_TXDMA_MASK_ALL = (TX_ENT_MSK_PKT_PRT_ERR_MASK |
+ TX_ENT_MSK_CONF_PART_ERR_MASK |
+ TX_ENT_MSK_NACK_PKT_RD_MASK |
+ TX_ENT_MSK_NACK_PREF_MASK |
+ TX_ENT_MSK_PREF_BUF_ECC_ERR_MASK |
+ TX_ENT_MSK_TX_RING_OFLOW_MASK |
+ TX_ENT_MSK_PKT_SIZE_ERR_MASK |
+ TX_ENT_MSK_MBOX_ERR_MASK |
+ TX_ENT_MSK_MK_MASK)
+} txdma_ent_msk_cfg_t;
+
+
+typedef struct _txdma_ring_errlog {
+ tx_rng_err_logl_t logl;
+ tx_rng_err_logh_t logh;
+} txdma_ring_errlog_t, *p_txdma_ring_errlog_t;
+
+/*
+ * Register offset (0x200 bytes for each channel) for logical pages registers.
+ */
+#define NXGE_TXLOG_OFFSET(x, channel) (x + TX_LOG_DMA_OFFSET(channel))
+
+/*
+ * Register offset (0x200 bytes for each channel) for transmit ring registers.
+ * (Ring configuration, kick register, event mask, control and status,
+ * mailbox, prefetch, ring errors).
+ */
+#define NXGE_TXDMA_OFFSET(x, v, channel) (x + \
+ (!v ? DMC_OFFSET(channel) : TDMC_PIOVADDR_OFFSET(channel)))
+/*
+ * Register offset (0x8 bytes for each port) for transmit mapping registers.
+ */
+#define NXGE_TXDMA_MAP_OFFSET(x, port) (x + TX_DMA_MAP_PORT_OFFSET(port))
+
+/*
+ * Register offset (0x10 bytes for each channel) for transmit DRR and ring
+ * usage registers.
+ */
+#define NXGE_TXDMA_DRR_OFFSET(x, channel) (x + \
+ TXDMA_DRR_RNG_USE_OFFSET(channel))
+
+/*
+ * PIO macros to read and write the transmit registers.
+ */
+#define TX_LOG_REG_READ64(handle, reg, channel, val_p) \
+ NXGE_REG_RD64(handle, NXGE_TXLOG_OFFSET(reg, channel), val_p)
+
+#define TX_LOG_REG_WRITE64(handle, reg, channel, data) \
+ NXGE_REG_WR64(handle, NXGE_TXLOG_OFFSET(reg, channel), data)
+
+#define TXDMA_REG_READ64(handle, reg, channel, val_p) \
+ NXGE_REG_RD64(handle, \
+ (NXGE_TXDMA_OFFSET(reg, handle.is_vraddr, channel)), val_p)
+
+#define TXDMA_REG_WRITE64(handle, reg, channel, data) \
+ NXGE_REG_WR64(handle, \
+ NXGE_TXDMA_OFFSET(reg, handle.is_vraddr, channel), data)
+
+#define TX_DRR_RNGUSE_REG_READ64(handle, reg, channel, val_p) \
+ NXGE_REG_RD64(handle, (NXGE_TXDMA_DRR_OFFSET(reg, channel)), val_p)
+
+#define TX_DRR_RNGUSE_REG_WRITE64(handle, reg, channel, data) \
+ NXGE_REG_WR64(handle, NXGE_TXDMA_DRR_OFFSET(reg, channel), data)
+
+/*
+ * Transmit Descriptor Definitions.
+ */
+#define TXDMA_DESC_SIZE (sizeof (tx_desc_t))
+
+#define NPI_TXDMA_GATHER_INDEX(index) \
+ ((index <= TX_MAX_GATHER_POINTERS)) ? NPI_SUCCESS : \
+ (NPI_TXDMA_GATHER_INVALID)
+
+/*
+ * Transmit NPI error codes
+ */
+#define TXDMA_ER_ST (TXDMA_BLK_ID << NPI_BLOCK_ID_SHIFT)
+#define TXDMA_ID_SHIFT(n) (n << NPI_PORT_CHAN_SHIFT)
+
+#define TXDMA_HW_STOP_FAILED (NPI_BK_HW_ER_START | 0x1)
+#define TXDMA_HW_RESUME_FAILED (NPI_BK_HW_ER_START | 0x2)
+
+#define TXDMA_GATHER_INVALID (NPI_BK_ERROR_START | 0x1)
+#define TXDMA_XFER_LEN_INVALID (NPI_BK_ERROR_START | 0x2)
+
+#define NPI_TXDMA_OPCODE_INVALID(n) (TXDMA_ID_SHIFT(n) | \
+ TXDMA_ER_ST | OPCODE_INVALID)
+
+#define NPI_TXDMA_FUNC_INVALID(n) (TXDMA_ID_SHIFT(n) | \
+ TXDMA_ER_ST | PORT_INVALID)
+#define NPI_TXDMA_CHANNEL_INVALID(n) (TXDMA_ID_SHIFT(n) | \
+ TXDMA_ER_ST | CHANNEL_INVALID)
+
+#define NPI_TXDMA_PAGE_INVALID(n) (TXDMA_ID_SHIFT(n) | \
+ TXDMA_ER_ST | LOGICAL_PAGE_INVALID)
+
+#define NPI_TXDMA_REGISTER_INVALID (TXDMA_ER_ST | REGISTER_INVALID)
+#define NPI_TXDMA_COUNTER_INVALID (TXDMA_ER_ST | COUNTER_INVALID)
+#define NPI_TXDMA_CONFIG_INVALID (TXDMA_ER_ST | CONFIG_INVALID)
+
+
+#define NPI_TXDMA_GATHER_INVALID (TXDMA_ER_ST | TXDMA_GATHER_INVALID)
+#define NPI_TXDMA_XFER_LEN_INVALID (TXDMA_ER_ST | TXDMA_XFER_LEN_INVALID)
+
+#define NPI_TXDMA_RESET_FAILED (TXDMA_ER_ST | RESET_FAILED)
+#define NPI_TXDMA_STOP_FAILED (TXDMA_ER_ST | TXDMA_HW_STOP_FAILED)
+#define NPI_TXDMA_RESUME_FAILED (TXDMA_ER_ST | TXDMA_HW_RESUME_FAILED)
+
+/*
+ * Transmit DMA Channel NPI Prototypes.
+ */
+npi_status_t npi_txdma_mode32_set(npi_handle_t, boolean_t);
+npi_status_t npi_txdma_log_page_set(npi_handle_t, uint8_t,
+ p_dma_log_page_t);
+npi_status_t npi_txdma_log_page_get(npi_handle_t, uint8_t,
+ p_dma_log_page_t);
+npi_status_t npi_txdma_log_page_handle_set(npi_handle_t, uint8_t,
+ p_log_page_hdl_t);
+npi_status_t npi_txdma_log_page_config(npi_handle_t, io_op_t,
+ txdma_log_cfg_t, uint8_t, p_dma_log_page_t);
+npi_status_t npi_txdma_log_page_vld_config(npi_handle_t, io_op_t,
+ uint8_t, p_log_page_vld_t);
+npi_status_t npi_txdma_drr_weight_set(npi_handle_t, uint8_t,
+ uint32_t);
+npi_status_t npi_txdma_channel_reset(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_init_enable(npi_handle_t,
+ uint8_t);
+npi_status_t npi_txdma_channel_enable(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_disable(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_resume(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_mmk_clear(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_mbox_enable(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_channel_control(npi_handle_t,
+ txdma_cs_cntl_t, uint8_t);
+npi_status_t npi_txdma_control_status(npi_handle_t, io_op_t,
+ uint8_t, p_tx_cs_t);
+
+npi_status_t npi_txdma_event_mask(npi_handle_t, io_op_t,
+ uint8_t, p_tx_dma_ent_msk_t);
+npi_status_t npi_txdma_event_mask_config(npi_handle_t, io_op_t,
+ uint8_t, txdma_ent_msk_cfg_t *);
+npi_status_t npi_txdma_event_mask_mk_out(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_event_mask_mk_in(npi_handle_t, uint8_t);
+
+npi_status_t npi_txdma_ring_addr_set(npi_handle_t, uint8_t,
+ uint64_t, uint32_t);
+npi_status_t npi_txdma_ring_config(npi_handle_t, io_op_t,
+ uint8_t, uint64_t *);
+npi_status_t npi_txdma_mbox_config(npi_handle_t, io_op_t,
+ uint8_t, uint64_t *);
+npi_status_t npi_txdma_desc_gather_set(npi_handle_t,
+ p_tx_desc_t, uint8_t,
+ boolean_t, uint8_t,
+ uint64_t, uint32_t);
+
+npi_status_t npi_txdma_desc_gather_sop_set(npi_handle_t,
+ p_tx_desc_t, boolean_t, uint8_t);
+
+npi_status_t npi_txdma_desc_gather_sop_set_1(npi_handle_t,
+ p_tx_desc_t, boolean_t, uint8_t,
+ uint32_t);
+
+npi_status_t npi_txdma_desc_set_xfer_len(npi_handle_t,
+ p_tx_desc_t, uint32_t);
+
+npi_status_t npi_txdma_desc_set_zero(npi_handle_t, uint16_t);
+npi_status_t npi_txdma_desc_mem_get(npi_handle_t, uint16_t,
+ p_tx_desc_t);
+npi_status_t npi_txdma_desc_kick_reg_set(npi_handle_t, uint8_t,
+ uint16_t, boolean_t);
+npi_status_t npi_txdma_desc_kick_reg_get(npi_handle_t, uint8_t,
+ p_tx_ring_kick_t);
+npi_status_t npi_txdma_ring_head_get(npi_handle_t, uint8_t,
+ p_tx_ring_hdl_t);
+npi_status_t npi_txdma_channel_mbox_get(npi_handle_t, uint8_t,
+ p_txdma_mailbox_t);
+npi_status_t npi_txdma_channel_pre_state_get(npi_handle_t,
+ uint8_t, p_tx_dma_pre_st_t);
+npi_status_t npi_txdma_ring_error_get(npi_handle_t,
+ uint8_t, p_txdma_ring_errlog_t);
+npi_status_t npi_txdma_inj_par_error_clear(npi_handle_t);
+npi_status_t npi_txdma_inj_par_error_set(npi_handle_t,
+ uint32_t);
+npi_status_t npi_txdma_inj_par_error_update(npi_handle_t,
+ uint32_t);
+npi_status_t npi_txdma_inj_par_error_get(npi_handle_t,
+ uint32_t *);
+npi_status_t npi_txdma_dbg_sel_set(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_training_vector_set(npi_handle_t,
+ uint32_t);
+void npi_txdma_dump_desc_one(npi_handle_t, p_tx_desc_t,
+ int);
+npi_status_t npi_txdma_dump_tdc_regs(npi_handle_t, uint8_t);
+npi_status_t npi_txdma_dump_fzc_regs(npi_handle_t);
+npi_status_t npi_txdma_inj_int_error_set(npi_handle_t, uint8_t,
+ p_tdmc_intr_dbg_t);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_TXDMA_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_vir.c b/usr/src/uts/sun4v/io/nxge/npi/npi_vir.c
new file mode 100644
index 0000000000..51d1097364
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_vir.c
@@ -0,0 +1,1504 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifdef SOLARIS
+#pragma ident "%Z%%M% %I% %E% SMI"
+#endif
+
+#include <npi_vir.h>
+
+/* One register only */
+uint64_t pio_offset[] = {
+ DEV_FUNC_SR_REG
+};
+
+const char *pio_name[] = {
+ "DEV_FUNC_SR_REG",
+};
+
+/* One register only */
+uint64_t fzc_pio_offset[] = {
+ MULTI_PART_CTL_REG,
+ LDGITMRES_REG
+};
+
+const char *fzc_pio_name[] = {
+ "MULTI_PART_CTL_REG",
+ "LDGITMRES_REG"
+};
+
+/* 64 sets */
+uint64_t fzc_pio_dma_bind_offset[] = {
+ DMA_BIND_REG
+};
+
+const char *fzc_pio_dma_bind_name[] = {
+ "DMA_BIND_REG",
+};
+
+/* 69 logical devices */
+uint64_t fzc_pio_ldgnum_offset[] = {
+ LDG_NUM_REG
+};
+
+const char *fzc_pio_ldgnum_name[] = {
+ "LDG_NUM_REG",
+};
+
+/* PIO_LDSV, 64 sets by 8192 bytes */
+uint64_t pio_ldsv_offset[] = {
+ LDSV0_REG,
+ LDSV1_REG,
+ LDSV2_REG,
+ LDGIMGN_REG
+};
+const char *pio_ldsv_name[] = {
+ "LDSV0_REG",
+ "LDSV1_REG",
+ "LDSV2_REG",
+ "LDGIMGN_REG"
+};
+
+/* PIO_IMASK0: 64 by 8192 */
+uint64_t pio_imask0_offset[] = {
+ LD_IM0_REG,
+};
+
+const char *pio_imask0_name[] = {
+ "LD_IM0_REG",
+};
+
+/* PIO_IMASK1: 5 by 8192 */
+uint64_t pio_imask1_offset[] = {
+ LD_IM1_REG
+};
+
+const char *pio_imask1_name[] = {
+ "LD_IM1_REG"
+};
+
+/* SID: 64 by 8 */
+uint64_t fzc_pio_sid_offset[] = {
+ SID_REG
+};
+
+const char *fzc_pio_sid_name[] = {
+ "SID_REG"
+};
+
+npi_status_t
+npi_vir_dump_pio_fzc_regs_one(npi_handle_t handle)
+{
+ uint64_t value;
+ int num_regs, i;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nPIO FZC Common Register Dump\n"));
+
+ num_regs = sizeof (pio_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ NXGE_REG_RD64(handle, pio_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ pio_offset[i],
+ pio_name[i], value));
+ }
+
+ num_regs = sizeof (fzc_pio_offset) / sizeof (uint64_t);
+ for (i = 0; i < num_regs; i++) {
+ NXGE_REG_RD64(handle, fzc_pio_offset[i], &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
+ "%s\t 0x%08llx \n",
+ fzc_pio_offset[i],
+ fzc_pio_name[i], value));
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n PIO FZC Register Dump Done \n"));
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_vir_dump_ldgnum(npi_handle_t handle)
+{
+ uint64_t value = 0, offset = 0;
+ int num_regs, i, ldv;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nFZC PIO LDG Number Register Dump\n"));
+
+ num_regs = sizeof (fzc_pio_ldgnum_offset) / sizeof (uint64_t);
+ for (ldv = 0; ldv < NXGE_INT_MAX_LDS; ldv++) {
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ offset = fzc_pio_ldgnum_offset[i] + 8 * ldv;
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "Logical Device %d: 0x%08llx "
+ "%s\t 0x%08llx \n",
+ ldv, offset,
+ fzc_pio_ldgnum_name[i], value));
+ }
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FZC PIO LDG Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_vir_dump_ldsv(npi_handle_t handle)
+{
+ uint64_t value, offset;
+ int num_regs, i, ldg;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nLD Device State Vector Register Dump\n"));
+
+ num_regs = sizeof (pio_ldsv_offset) / sizeof (uint64_t);
+ for (ldg = 0; ldg < NXGE_INT_MAX_LDGS; ldg++) {
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ offset = pio_ldsv_offset[i] + 8192 * ldg;
+ NXGE_REG_RD64(handle, offset, &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "LDG State: group %d: 0x%08llx "
+ "%s\t 0x%08llx \n",
+ ldg, offset,
+ pio_ldsv_name[i], value));
+ }
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FZC PIO LDG Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_vir_dump_imask0(npi_handle_t handle)
+{
+ uint64_t value, offset;
+ int num_regs, i, ldv;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nLD Interrupt Mask Register Dump\n"));
+
+ num_regs = sizeof (pio_imask0_offset) / sizeof (uint64_t);
+ for (ldv = 0; ldv < 64; ldv++) {
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ offset = pio_imask0_offset[i] + 8192 * ldv;
+ NXGE_REG_RD64(handle, offset,
+ &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "LD Interrupt Mask %d: 0x%08llx "
+ "%s\t 0x%08llx \n",
+ ldv, offset,
+ pio_imask0_name[i], value));
+ }
+ }
+ num_regs = sizeof (pio_imask1_offset) / sizeof (uint64_t);
+ for (ldv = 64; ldv < 69; ldv++) {
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ offset = pio_imask1_offset[i] + 8192 * (ldv - 64);
+ NXGE_REG_RD64(handle, offset,
+ &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "LD Interrupt Mask %d: 0x%08llx "
+ "%s\t 0x%08llx \n",
+ ldv, offset,
+ pio_imask1_name[i], value));
+ }
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FZC PIO Logical Device Group Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_vir_dump_sid(npi_handle_t handle)
+{
+ uint64_t value, offset;
+ int num_regs, i, ldg;
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\nSystem Interrupt Data Register Dump\n"));
+
+ num_regs = sizeof (fzc_pio_sid_offset) / sizeof (uint64_t);
+ for (ldg = 0; ldg < NXGE_INT_MAX_LDGS; ldg++) {
+ for (i = 0; i < num_regs; i++) {
+ value = 0;
+ offset = fzc_pio_sid_offset[i] + 8 * ldg;
+ NXGE_REG_RD64(handle, offset,
+ &value);
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "SID for group %d: 0x%08llx "
+ "%s\t 0x%08llx \n",
+ ldg, offset,
+ fzc_pio_sid_name[i], value));
+ }
+ }
+
+ NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
+ "\n FZC PIO SID Register Dump Done \n"));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_dev_func_sr_init():
+ * This function is called to initialize the device function
+ * shared register (set the software implementation lock
+ * state to FREE).
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If initialization is complete successfully.
+ * (set sr bits to free).
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t
+npi_dev_func_sr_init(npi_handle_t handle)
+{
+ dev_func_sr_t sr;
+ int status = NPI_SUCCESS;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ if (!sr.bits.ldw.tas) {
+ /*
+ * After read, this bit is set to 1 by hardware.
+ * We own it if tas bit read as 0.
+ * Set the lock state to free if it is in reset state.
+ */
+ if (!sr.bits.ldw.sr) {
+ /* reset state */
+ sr.bits.ldw.sr |= NPI_DEV_SR_LOCK_ST_FREE;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ }
+
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_init"
+ " sr <0x%x>",
+ sr.bits.ldw.sr));
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_init"
+ " tas busy <0x%x>",
+ sr.bits.ldw));
+ status = NPI_VIR_TAS_BUSY(sr.bits.ldw.funcid);
+ }
+
+ return (status);
+}
+
+/*
+ * npi_dev_func_sr_lock_enter():
+ * This function is called to lock the function shared register
+ * by setting the lock state to busy.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If the function id can own the lock.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_SR_RESET
+ * VIR_SR_BUSY
+ * VIR_SR_INVALID
+ * VIR_TAS_BUSY
+ */
+npi_status_t
+npi_dev_func_sr_lock_enter(npi_handle_t handle)
+{
+ dev_func_sr_t sr;
+ int status = NPI_SUCCESS;
+ uint32_t state;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ if (!sr.bits.ldw.tas) {
+ /*
+ * tas bit will be set to 1 by hardware.
+ * reset tas bit when we unlock the sr.
+ */
+ state = sr.bits.ldw.sr & NPI_DEV_SR_LOCK_ST_MASK;
+ switch (state) {
+ case NPI_DEV_SR_LOCK_ST_FREE:
+ /*
+ * set it to busy and our function id.
+ */
+ sr.bits.ldw.sr |= (NPI_DEV_SR_LOCK_ST_BUSY |
+ (sr.bits.ldw.funcid <<
+ NPI_DEV_SR_LOCK_FID_SHIFT));
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ break;
+
+ case NPI_DEV_SR_LOCK_ST_RESET:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_lock_enter"
+ " reset state <0x%x>",
+ sr.bits.ldw.sr));
+ status = NPI_VIR_SR_RESET(sr.bits.ldw.funcid);
+ break;
+
+ case NPI_DEV_SR_LOCK_ST_BUSY:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_lock_enter"
+ " busy <0x%x>",
+ sr.bits.ldw.sr));
+ status = NPI_VIR_SR_BUSY(sr.bits.ldw.funcid);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_lock_enter",
+ " invalid state",
+ sr.bits.ldw.sr));
+ status = NPI_VIR_SR_INVALID(sr.bits.ldw.funcid);
+ break;
+ }
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_lock_enter",
+ " tas busy", sr.bits.ldw));
+ status = NPI_VIR_TAS_BUSY(sr.bits.ldw.funcid);
+ }
+
+ return (status);
+}
+
+/*
+ * npi_dev_func_sr_lock_free():
+ * This function is called to free the function shared register
+ * by setting the lock state to free.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If the function id can free the lock.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_SR_NOTOWNER
+ * VIR_TAS_NOTREAD
+ */
+npi_status_t
+npi_dev_func_sr_lock_free(npi_handle_t handle)
+{
+ dev_func_sr_t sr;
+ int status = NPI_SUCCESS;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ if (sr.bits.ldw.tas) {
+ if (sr.bits.ldw.funcid == NPI_GET_LOCK_OWNER(sr.bits.ldw.sr)) {
+ sr.bits.ldw.sr &= NPI_DEV_SR_IMPL_ST_MASK;
+ sr.bits.ldw.sr |= NPI_DEV_SR_LOCK_ST_FREE;
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ } else {
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_dev_func_sr_lock_free"
+ " not owner <0x%x>",
+ sr.bits.ldw.sr));
+ status = NPI_VIR_SR_NOTOWNER(sr.bits.ldw.funcid);
+ }
+ } else {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_dev_func_sr_lock_free",
+ " invalid tas state <0x%x>",
+ sr.bits.ldw.tas));
+ status = NPI_VIR_TAS_NOTREAD(sr.bits.ldw.funcid);
+ }
+
+ return (status);
+}
+
+/*
+ * npi_dev_func_sr_funcid_get():
+ * This function is called to get the caller's function ID.
+ * (based on address bits [25:26] on read access.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear.) This function will write 0 to clear
+ * the TAS bit if we own it.
+ * Parameters:
+ * handle - NPI handle
+ * funcid_p - pointer to store the function id.
+ * Return:
+ * NPI_SUCCESS - If get function id is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_dev_func_sr_funcid_get(npi_handle_t handle, uint8_t *funcid_p)
+{
+ dev_func_sr_t sr;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ *funcid_p = NXGE_VAL(DEV_FUNC_SR_FUNCID, sr.value);
+ if (!sr.bits.ldw.tas) {
+ /*
+ * After read, this bit is set to 1 by hardware.
+ * We own it if tas bit read as 0.
+ */
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_dev_func_sr_sr_get():
+ * This function is called to get the shared register value.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear if we own it.)
+ *
+ * Parameters:
+ * handle - NPI handle
+ * sr_p - pointer to store the shared value of this register.
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value get is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t
+npi_dev_func_sr_sr_raw_get(npi_handle_t handle, uint16_t *sr_p)
+{
+ dev_func_sr_t sr;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ *sr_p = NXGE_VAL(DEV_FUNC_SR_FUNCID, sr.value);
+ if (!sr.bits.ldw.tas) {
+ /*
+ * After read, this bit is set to 1 by hardware.
+ * We own it if tas bit read as 0.
+ */
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_dev_func_sr_sr_get():
+ * This function is called to get the shared register value.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear if we own it.)
+ *
+ * Parameters:
+ * handle - NPI handle
+ * sr_p - pointer to store the shared value of this register.
+ * . this will get only non-lock, non-function id portion
+ * . of the register
+ *
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value get is complete successfully.
+ *
+ * Error:
+ */
+
+npi_status_t
+npi_dev_func_sr_sr_get(npi_handle_t handle, uint16_t *sr_p)
+{
+ dev_func_sr_t sr;
+ uint16_t sr_impl = 0;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ sr_impl = NXGE_VAL(DEV_FUNC_SR_FUNCID, sr.value);
+ *sr_p = (sr_impl << NPI_DEV_SR_IMPL_ST_SHIFT);
+ if (!sr.bits.ldw.tas) {
+ /*
+ * After read, this bit is set to 1 by hardware.
+ * We own it if tas bit read as 0.
+ */
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_dev_func_sr_sr_get_set_clear():
+ * This function is called to set the shared register value.
+ * (Shared register must be read first. If tas bit is 0, then
+ * it implies that the software can proceed to set). After
+ * setting, tas bit will be cleared.
+ * Parameters:
+ * handle - NPI handle
+ * impl_sr - shared value to set (only the 8 bit
+ * implementation specific state info).
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value is set successfully.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t
+npi_dev_func_sr_sr_get_set_clear(npi_handle_t handle, uint16_t impl_sr)
+{
+ dev_func_sr_t sr;
+ int status;
+
+ status = npi_dev_func_sr_lock_enter(handle);
+ if (status != NPI_SUCCESS) {
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_dev_func_sr_src_get_set_clear"
+ " unable to acquire lock:"
+ " status <0x%x>", status));
+ return (status);
+ }
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ sr.bits.ldw.sr |= (impl_sr << NPI_DEV_SR_IMPL_ST_SHIFT);
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+
+ return (npi_dev_func_sr_lock_free(handle));
+}
+
+/*
+ * npi_dev_func_sr_sr_set_only():
+ * This function is called to only set the shared register value.
+ * Parameters:
+ * handle - NPI handle
+ * impl_sr - shared value to set.
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value is set successfully.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t
+npi_dev_func_sr_sr_set_only(npi_handle_t handle, uint16_t impl_sr)
+{
+ int status = NPI_SUCCESS;
+ dev_func_sr_t sr;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ /* must be the owner */
+ if (sr.bits.ldw.funcid == NPI_GET_LOCK_OWNER(sr.bits.ldw.sr)) {
+ sr.bits.ldw.sr |= (impl_sr << NPI_DEV_SR_IMPL_ST_SHIFT);
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ } else {
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_dev_func_sr_sr_set_only"
+ " not owner <0x%x>",
+ sr.bits.ldw.sr));
+ status = NPI_VIR_SR_NOTOWNER(sr.bits.ldw.funcid);
+ }
+
+ return (status);
+}
+
+/*
+ * npi_dev_func_sr_busy():
+ * This function is called to see if we can own the device.
+ * It will not reset the tas bit.
+ * Parameters:
+ * handle - NPI handle
+ * busy_p - pointer to store busy flag.
+ * (B_TRUE: device is in use, B_FALSE: free).
+ * Return:
+ * NPI_SUCCESS - If tas bit is read successfully.
+ * Error:
+ */
+npi_status_t
+npi_dev_func_sr_busy(npi_handle_t handle, boolean_t *busy_p)
+{
+ dev_func_sr_t sr;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ if (!sr.bits.ldw.tas) {
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+ *busy_p = B_FALSE;
+ } else {
+ /* Other function already owns it */
+ *busy_p = B_TRUE;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_dev_func_sr_tas_get():
+ * This function is called to get the tas bit
+ * (after read, this bit is always set to 1, software write 0
+ * to clear it).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * tas_p - pointer to store the tas value
+ *
+ * Return:
+ * NPI_SUCCESS - If tas value get is complete successfully.
+ * Error:
+ */
+npi_status_t
+npi_dev_func_sr_tas_get(npi_handle_t handle, uint8_t *tas_p)
+{
+ dev_func_sr_t sr;
+
+ NXGE_REG_RD64(handle, DEV_FUNC_SR_REG, &sr.value);
+ *tas_p = sr.bits.ldw.tas;
+ if (!sr.bits.ldw.tas) {
+ sr.bits.ldw.tas = 0;
+ NXGE_REG_WR64(handle, DEV_FUNC_SR_REG, sr.value);
+
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_mpc_set():
+ * This function is called to enable the write access
+ * to FZC region to function zero.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ */
+npi_status_t
+npi_fzc_mpc_set(npi_handle_t handle, boolean_t mpc)
+{
+ multi_part_ctl_t mp;
+
+ mp.value = 0;
+ if (mpc) {
+ mp.bits.ldw.mpc = 1;
+ }
+ NXGE_REG_WR64(handle, MULTI_PART_CTL_REG, mp.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_mpc_get():
+ * This function is called to get the access mode.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS -
+ *
+ */
+npi_status_t
+npi_fzc_mpc_get(npi_handle_t handle, boolean_t *mpc_p)
+{
+ multi_part_ctl_t mpc;
+
+ mpc.value = 0;
+ NXGE_REG_RD64(handle, MULTI_PART_CTL_REG, &mpc.value);
+ *mpc_p = mpc.bits.ldw.mpc;
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_dma_bind_set():
+ * This function is called to set DMA binding register.
+ * Parameters:
+ * handle - NPI handle
+ * dma_bind - NPI defined data structure that
+ * contains the tx/rx channel binding info.
+ * to set.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_fzc_dma_bind_set(npi_handle_t handle, fzc_dma_bind_t dma_bind)
+{
+ dma_bind_t bind;
+ int status;
+ uint8_t fn, region, id, tn, rn;
+
+ fn = dma_bind.function_id;
+ region = dma_bind.sub_vir_region;
+ id = dma_bind.vir_index;
+ tn = dma_bind.tx_channel;
+ rn = dma_bind.rx_channel;
+
+ DMA_BIND_VADDR_VALIDATE(fn, region, id, status);
+ if (status) {
+ return (status);
+ }
+
+ if (dma_bind.tx_bind) {
+ DMA_BIND_TX_VALIDATE(tn, status);
+ if (status) {
+ return (status);
+ }
+ }
+
+ if (dma_bind.rx_bind) {
+ DMA_BIND_RX_VALIDATE(rn, status);
+ if (status) {
+ return (status);
+ }
+ }
+
+ bind.value = 0;
+ if (dma_bind.tx_bind) {
+ bind.bits.ldw.tx_bind = 1;
+ bind.bits.ldw.tx = tn;
+ }
+ if (dma_bind.rx_bind) {
+ bind.bits.ldw.rx_bind = 1;
+ bind.bits.ldw.rx = rn;
+ }
+
+ NXGE_REG_WR64(handle, DMA_BIND_REG +
+ DMA_BIND_REG_OFFSET(fn, rn, id), bind.value);
+
+ return (status);
+}
+
+/*
+ * npi_fzc_ldg_num_set():
+ * This function is called to set up a logical group number that
+ * a logical device belongs to.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device number (0 - 68)
+ * ldg - logical device group number (0 - 63)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ *
+ */
+npi_status_t
+npi_fzc_ldg_num_set(npi_handle_t handle, uint8_t ld, uint8_t ldg)
+{
+ ldg_num_t gnum;
+
+ if (!LD_VALID(ld)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_ldg_num_set"
+ "ld <0x%x>", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ }
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_ldg_num_set"
+ " ldg <0x%x>", ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ld));
+ }
+
+ gnum.value = 0;
+ gnum.bits.ldw.num = ldg;
+
+ NXGE_REG_WR64(handle, LDG_NUM_REG + LD_NUM_OFFSET(ld),
+ gnum.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_ldg_num_get():
+ * This function is called to get the logical device group that
+ * a logical device belongs to.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device number (0 - 68)
+ * *ldg_p - pointer to store its group number.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_ldg_num_get(npi_handle_t handle, uint8_t ld, uint8_t *ldg_p)
+{
+ uint64_t val;
+
+ if (!LD_VALID(ld)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_ldg_num_get"
+ " Invalid Input:",
+ " ld <0x%x>", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ }
+
+ NXGE_REG_RD64(handle, LDG_NUM_REG + LD_NUM_OFFSET(ld), &val);
+
+ *ldg_p = (uint8_t)(val & LDG_NUM_NUM_MASK);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_ldsv_ldfs_get():
+ * This function is called to get device state vectors.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * *ldf_p - pointer to store ldf0 and ldf1 flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_ldsv_ldfs_get(npi_handle_t handle, uint8_t ldg, uint64_t *vector0_p,
+ uint64_t *vector1_p, uint64_t *vector2_p)
+{
+ int status;
+
+ if ((status = npi_ldsv_get(handle, ldg, VECTOR0, vector0_p))) {
+ return (status);
+ }
+ if ((status = npi_ldsv_get(handle, ldg, VECTOR1, vector1_p))) {
+ return (status);
+ }
+ if ((status = npi_ldsv_get(handle, ldg, VECTOR2, vector2_p))) {
+ return (status);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_ldsv_get():
+ * This function is called to get device state vectors.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ldf_type - either LDF0 (0) or LDF1 (1)
+ * vector - vector type (0, 1 or 2)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_ldsv_get(npi_handle_t handle, uint8_t ldg, ldsv_type_t vector,
+ uint64_t *ldf_p)
+{
+ uint64_t offset;
+
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ldsv_get"
+ " Invalid Input "
+ " ldg <0x%x>", ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ldg));
+ }
+
+ switch (vector) {
+ case VECTOR0:
+ offset = LDSV0_REG + LDSV_OFFSET(ldg);
+ break;
+
+ case VECTOR1:
+ offset = LDSV1_REG + LDSV_OFFSET(ldg);
+ break;
+
+ case VECTOR2:
+ offset = LDSV2_REG + LDSV_OFFSET(ldg);
+ break;
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ldsv_get"
+ " Invalid Input: "
+ " ldsv type <0x%x>", vector));
+ return (NPI_FAILURE | NPI_VIR_LDSV_INVALID(vector));
+ }
+
+ NXGE_REG_RD64(handle, offset, ldf_p);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_ldsv_ld_get():
+ * This function is called to get the flag bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * ldf_type - either LDF0 (0) or LDF1 (1)
+ * vector - vector type (0, 1 or 2)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_ldsv_ld_get(npi_handle_t handle, uint8_t ldg, uint8_t ld,
+ ldsv_type_t vector, ldf_type_t ldf_type, boolean_t *flag_p)
+{
+ uint64_t sv;
+ uint64_t offset;
+
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ldsv_ld_get"
+ " Invalid Input: "
+ " ldg <0x%x>", ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ldg));
+ }
+ if (!LD_VALID(ld)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ldsv_ld_get Invalid Input: "
+ " ld <9x%x>", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ } else if (vector == VECTOR2 && ld < NXGE_MAC_LD_START) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_ldsv_ld_get Invalid Input:"
+ " ld-vector2 <0x%x>", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ }
+
+ switch (vector) {
+ case VECTOR0:
+ offset = LDSV0_REG + LDSV_OFFSET(ldg);
+ break;
+
+ case VECTOR1:
+ offset = LDSV1_REG + LDSV_OFFSET(ldg);
+ break;
+
+ case VECTOR2:
+ offset = LDSV2_REG + LDSV_OFFSET(ldg);
+
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_ldsv_get"
+ "ldsv", vector));
+ return (NPI_FAILURE | NPI_VIR_LDSV_INVALID(vector));
+ }
+
+ NXGE_REG_RD64(handle, offset, &sv);
+ if (vector != VECTOR2) {
+ *flag_p = ((sv >> ld) & LDSV_MASK_ALL);
+ } else {
+ if (ldf_type) {
+ *flag_p = (((sv >> LDSV2_LDF1_SHIFT) >>
+ (ld - NXGE_MAC_LD_START)) & LDSV_MASK_ALL);
+ } else {
+ *flag_p = (((sv >> LDSV2_LDF0_SHIFT) >>
+ (ld - NXGE_MAC_LD_START)) & LDSV_MASK_ALL);
+ }
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_ldsv_ld_ldf0_get():
+ * This function is called to get the ldf0 bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_ldsv_ld_ldf0_get(npi_handle_t handle, uint8_t ldg, uint8_t ld,
+ boolean_t *flag_p)
+{
+ ldsv_type_t vector;
+
+ if (ld >= NXGE_MAC_LD_START) {
+ vector = VECTOR2;
+ }
+
+ return (npi_ldsv_ld_get(handle, ldg, ld, vector, LDF0, flag_p));
+}
+
+/*
+ * npi_ldsv_ld_ldf1_get():
+ * This function is called to get the ldf1 bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_ldsv_ld_ldf1_get(npi_handle_t handle, uint8_t ldg, uint8_t ld,
+ boolean_t *flag_p)
+{
+ ldsv_type_t vector;
+
+ if (ld >= NXGE_MAC_LD_START) {
+ vector = VECTOR2;
+ }
+
+ return (npi_ldsv_ld_get(handle, ldg, ld, vector, LDF1, flag_p));
+}
+
+/*
+ * npi_intr_mask_set():
+ * This function is called to select the mask bits for both ldf0 and ldf1.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device (0 - 68)
+ * ldf_mask - mask value to set (both ldf0 and ldf1).
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_intr_mask_set(npi_handle_t handle, uint8_t ld, uint8_t ldf_mask)
+{
+ uint64_t offset;
+
+ if (!LD_VALID(ld)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_mask_set ld", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ }
+
+ ldf_mask &= LD_IM0_MASK;
+ offset = LDSV_OFFSET_MASK(ld);
+
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ "npi_intr_mask_set: ld %d "
+ " offset 0x%0llx "
+ " mask 0x%x",
+ ld, offset, ldf_mask));
+
+ NXGE_REG_WR64(handle, offset, (uint64_t)ldf_mask);
+
+ return (NPI_SUCCESS);
+
+}
+
+/*
+ * npi_intr_mask_get():
+ * This function is called to get the mask bits.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device (0 - 68)
+ * ldf_mask - pointer to store mask bits info.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_intr_mask_get(npi_handle_t handle, uint8_t ld, uint8_t *ldf_mask_p)
+{
+ uint64_t offset;
+ uint64_t val;
+
+ if (!LD_VALID(ld)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_mask_get ld", ld));
+ return (NPI_FAILURE | NPI_VIR_LD_INVALID(ld));
+ }
+
+ offset = LDSV_OFFSET_MASK(ld);
+
+ NXGE_REG_RD64(handle, offset, &val);
+
+ *ldf_mask_p = (uint8_t)(val & LD_IM_MASK);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_intr_ldg_mgmt_set():
+ * This function is called to set interrupt timer and arm bit.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * arm - B_TRUE (arm) B_FALSE (disable)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_intr_ldg_mgmt_set(npi_handle_t handle, uint8_t ldg, boolean_t arm,
+ uint8_t timer)
+{
+ ldgimgm_t mgm;
+ uint64_t val;
+
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_ldg_mgmt_set"
+ " Invalid Input: "
+ " ldg <0x%x>", ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ldg));
+ }
+ if (!LD_INTTIMER_VALID(timer)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_ldg_mgmt_set Invalid Input"
+ " timer <0x%x>", timer));
+ return (NPI_FAILURE | NPI_VIR_INTM_TM_INVALID(ldg));
+ }
+
+ if (arm) {
+ mgm.bits.ldw.arm = 1;
+ } else {
+ NXGE_REG_RD64(handle, LDGIMGN_REG + LDSV_OFFSET(ldg), &val);
+ mgm.value = val & LDGIMGM_ARM_MASK;
+ }
+
+ mgm.bits.ldw.timer = timer;
+ NXGE_REG_WR64(handle, LDGIMGN_REG + LDSV_OFFSET(ldg),
+ mgm.value);
+
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_intr_ldg_mgmt_set: ldg %d"
+ " reg offset 0x%x",
+ ldg, LDGIMGN_REG + LDSV_OFFSET(ldg)));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_intr_ldg_mgmt_timer_get():
+ * This function is called to get the timer counter
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * timer_p - pointer to store the timer counter.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_intr_ldg_mgmt_timer_get(npi_handle_t handle, uint8_t ldg, uint8_t *timer_p)
+{
+ uint64_t val;
+
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_ldg_mgmt_timer_get"
+ " Invalid Input: ldg <0x%x>", ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ldg));
+ }
+
+ NXGE_REG_RD64(handle, LDGIMGN_REG + LDSV_OFFSET(ldg), &val);
+
+ *timer_p = (uint8_t)(val & LDGIMGM_TIMER_MASK);
+
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_intr_ldg_mgmt_timer_get: ldg %d"
+ " reg offset 0x%x",
+ ldg, LDGIMGN_REG + LDSV_OFFSET(ldg)));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_intr_ldg_mgmt_arm():
+ * This function is called to arm the group.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_intr_ldg_mgmt_arm(npi_handle_t handle, uint8_t ldg)
+{
+ ldgimgm_t mgm;
+
+ if (!LDG_VALID(ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_intr_ldg_mgmt_arm"
+ " Invalid Input: ldg <0x%x>",
+ ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(ldg));
+ }
+
+ NXGE_REG_RD64(handle, (LDGIMGN_REG + LDSV_OFFSET(ldg)), &mgm.value);
+ mgm.bits.ldw.arm = 1;
+
+ NXGE_REG_WR64(handle, LDGIMGN_REG + LDSV_OFFSET(ldg),
+ mgm.value);
+ NPI_DEBUG_MSG((handle.function, NPI_VIR_CTL,
+ " npi_intr_ldg_mgmt_arm: ldg %d"
+ " reg offset 0x%x",
+ ldg, LDGIMGN_REG + LDSV_OFFSET(ldg)));
+
+ return (NPI_SUCCESS);
+}
+
+
+/*
+ * npi_fzc_ldg_timer_res_set():
+ * This function is called to set the timer resolution.
+ * Parameters:
+ * handle - NPI handle
+ * res - timer resolution (# of system clocks)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_ldg_timer_res_set(npi_handle_t handle, uint32_t res)
+{
+ if (res > LDGTITMRES_RES_MASK) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_ldg_timer_res_set"
+ " Invalid Input: res <0x%x>",
+ res));
+ return (NPI_FAILURE | NPI_VIR_TM_RES_INVALID);
+ }
+
+ NXGE_REG_WR64(handle, LDGITMRES_REG, (res & LDGTITMRES_RES_MASK));
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_ldg_timer_res_get():
+ * This function is called to get the timer resolution.
+ * Parameters:
+ * handle - NPI handle
+ * res_p - pointer to store the timer resolution.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_ldg_timer_res_get(npi_handle_t handle, uint8_t *res_p)
+{
+ uint64_t val;
+
+ NXGE_REG_RD64(handle, LDGITMRES_REG, &val);
+
+ *res_p = (uint8_t)(val & LDGIMGM_TIMER_MASK);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_sid_set():
+ * This function is called to set the system interrupt data.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical group (0 - 63)
+ * sid - NPI defined data to set
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_sid_set(npi_handle_t handle, fzc_sid_t sid)
+{
+ sid_t sd;
+
+ if (!LDG_VALID(sid.ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_sid_set"
+ " Invalid Input: ldg <0x%x>",
+ sid.ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(sid.ldg));
+ }
+ if (!sid.niu) {
+ if (!FUNC_VALID(sid.func)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_sid_set"
+ " Invalid Input: func <0x%x>",
+ sid.func));
+#if defined(SOLARIS) && defined(_KERNEL) && defined(NPI_DEBUG)
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ "invalid FUNC: npi_fzc_sid_set(%d)",
+ sid.func));
+#endif
+ return (NPI_FAILURE | NPI_VIR_FUNC_INVALID(sid.func));
+ }
+
+ if (!SID_VECTOR_VALID(sid.vector)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_sid_set"
+ " Invalid Input: vector <0x%x>",
+ sid.vector));
+#if defined(SOLARIS) && defined(_KERNEL) && defined(NPI_DEBUG)
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " invalid VECTOR: npi_fzc_sid_set(%d)",
+ sid.vector));
+#endif
+ return (NPI_FAILURE |
+ NPI_VIR_SID_VEC_INVALID(sid.vector));
+ }
+ }
+ sd.value = 0;
+ if (!sid.niu) {
+ sd.bits.ldw.data = ((sid.func << SID_DATA_FUNCNUM_SHIFT) |
+ (sid.vector & SID_DATA_INTNUM_MASK));
+ }
+#if defined(SOLARIS) && defined(_KERNEL) && defined(NPI_DEBUG)
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_sid_set: group %d 0x%llx",
+ sid.ldg, sd.value));
+#endif
+
+ NXGE_REG_WR64(handle, SID_REG + LDG_SID_OFFSET(sid.ldg), sd.value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_sid_get():
+ * This function is called to get the system interrupt data.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical group (0 - 63)
+ * sid_p - NPI defined data to get
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_sid_get(npi_handle_t handle, p_fzc_sid_t sid_p)
+{
+ sid_t sd;
+
+ if (!LDG_VALID(sid_p->ldg)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_fzc_sid_get"
+ " Invalid Input: ldg <0x%x>",
+ sid_p->ldg));
+ return (NPI_FAILURE | NPI_VIR_LDG_INVALID(sid_p->ldg));
+ }
+ NXGE_REG_RD64(handle, (SID_REG + LDG_SID_OFFSET(sid_p->ldg)),
+ &sd.value);
+ if (!sid_p->niu) {
+ sid_p->func = ((sd.bits.ldw.data & SID_DATA_FUNCNUM_MASK) >>
+ SID_DATA_FUNCNUM_SHIFT);
+ sid_p->vector = ((sd.bits.ldw.data & SID_DATA_INTNUM_MASK) >>
+ SID_DATA_INTNUM_SHIFT);
+ } else {
+ sid_p->vector = (sd.value & SID_DATA_MASK);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_sys_err_mask_set():
+ * This function is called to mask/unmask the device error mask bits.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * mask - set bit mapped mask
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_sys_err_mask_set(npi_handle_t handle, uint64_t mask)
+{
+ NXGE_REG_WR64(handle, SYS_ERR_MASK_REG, mask);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_sys_err_stat_get():
+ * This function is called to get the system error stats.
+ *
+ * Parameters:
+ * handle - NPI handle
+ * err_stat - sys_err_stat structure to hold stats.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t
+npi_fzc_sys_err_stat_get(npi_handle_t handle, p_sys_err_stat_t statp)
+{
+ NXGE_REG_RD64(handle, SYS_ERR_STAT_REG, &statp->value);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_fzc_rst_ctl_get(npi_handle_t handle, p_rst_ctl_t rstp)
+{
+ NXGE_REG_RD64(handle, RST_CTL_REG, &rstp->value);
+
+ return (NPI_SUCCESS);
+}
+
+/*
+ * npi_fzc_mpc_get():
+ * This function is called to get the access mode.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS -
+ *
+ */
+npi_status_t
+npi_fzc_rst_ctl_reset_mac(npi_handle_t handle, uint8_t port)
+{
+ rst_ctl_t rst;
+
+ rst.value = 0;
+ NXGE_REG_RD64(handle, RST_CTL_REG, &rst.value);
+ rst.value |= (1 << (RST_CTL_MAC_RST0_SHIFT + port));
+ NXGE_REG_WR64(handle, RST_CTL_REG, rst.value);
+
+ return (NPI_SUCCESS);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_vir.h b/usr/src/uts/sun4v/io/nxge/npi/npi_vir.h
new file mode 100644
index 0000000000..11aada4cf2
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_vir.h
@@ -0,0 +1,690 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_VIR_H
+#define _NPI_VIR_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_hw.h>
+
+/*
+ * Virtualization and Logical devices NPI error codes
+ */
+#define FUNCID_INVALID PORT_INVALID
+#define VIR_ERR_ST (VIR_BLK_ID << NPI_BLOCK_ID_SHIFT)
+#define VIR_ID_SHIFT(n) (n << NPI_PORT_CHAN_SHIFT)
+
+#define VIR_HW_BUSY (NPI_BK_HW_ERROR_START | 0x1)
+
+#define VIR_TAS_BUSY (NPI_BK_ERROR_START | 0x1)
+#define VIR_TAS_NOTREAD (NPI_BK_ERROR_START | 0x2)
+
+#define VIR_SR_RESET (NPI_BK_ERROR_START | 0x3)
+#define VIR_SR_FREE (NPI_BK_ERROR_START | 0x4)
+#define VIR_SR_BUSY (NPI_BK_ERROR_START | 0x5)
+#define VIR_SR_INVALID (NPI_BK_ERROR_START | 0x6)
+#define VIR_SR_NOTOWNER (NPI_BK_ERROR_START | 0x7)
+#define VIR_SR_INITIALIZED (NPI_BK_ERROR_START | 0x8)
+
+#define VIR_MPC_DENY (NPI_BK_ERROR_START | 0x10)
+
+#define VIR_BD_FUNC_INVALID (NPI_BK_ERROR_START | 0x20)
+#define VIR_BD_REG_INVALID (NPI_BK_ERROR_START | 0x21)
+#define VIR_BD_ID_INVALID (NPI_BK_ERROR_START | 0x22)
+#define VIR_BD_TXDMA_INVALID (NPI_BK_ERROR_START | 0x23)
+#define VIR_BD_RXDMA_INVALID (NPI_BK_ERROR_START | 0x24)
+
+#define VIR_LD_INVALID (NPI_BK_ERROR_START | 0x30)
+#define VIR_LDG_INVALID (NPI_BK_ERROR_START | 0x31)
+#define VIR_LDSV_INVALID (NPI_BK_ERROR_START | 0x32)
+
+#define VIR_INTM_TM_INVALID (NPI_BK_ERROR_START | 0x33)
+#define VIR_TM_RES_INVALID (NPI_BK_ERROR_START | 0x34)
+#define VIR_SID_VEC_INVALID (NPI_BK_ERROR_START | 0x35)
+
+#define NPI_VIR_OCODE_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | OPCODE_INVALID)
+#define NPI_VIR_FUNC_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | FUNCID_INVALID)
+#define NPI_VIR_CN_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | CHANNEL_INVALID)
+
+/*
+ * Errors codes of shared register functions.
+ */
+#define NPI_VIR_TAS_BUSY(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_TAS_BUSY)
+#define NPI_VIR_TAS_NOTREAD(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_TAS_NOTREAD)
+#define NPI_VIR_SR_RESET(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_SR_RESET)
+#define NPI_VIR_SR_FREE(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_SR_FREE)
+#define NPI_VIR_SR_BUSY(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_SR_BUSY)
+#define NPI_VIR_SR_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_SR_INVALID)
+#define NPI_VIR_SR_NOTOWNER(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_SR_NOTOWNER)
+#define NPI_VIR_SR_INITIALIZED(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_SR_INITIALIZED)
+
+/*
+ * Error codes of muti-partition control register functions.
+ */
+#define NPI_VIR_MPC_DENY (VIR_ERR_ST | VIR_MPU_DENY)
+
+/*
+ * Error codes of DMA binding functions.
+ */
+#define NPI_VIR_BD_FUNC_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_BD_FUNC_INVALID)
+#define NPI_VIR_BD_REG_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_BD_REG_INVALID)
+#define NPI_VIR_BD_ID_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_BD_ID_INVALID)
+#define NPI_VIR_BD_TXDMA_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_BD_TXDMA_INVALID)
+#define NPI_VIR_BD_RXDMA_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_BD_RXDMA_INVALID)
+
+/*
+ * Error codes of logical devices and groups functions.
+ */
+#define NPI_VIR_LD_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_LD_INVALID)
+#define NPI_VIR_LDG_INVALID(n) (VIR_ID_SHIFT(n) | VIR_ERR_ST | VIR_LDG_INVALID)
+#define NPI_VIR_LDSV_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_LDSV_INVALID)
+#define NPI_VIR_INTM_TM_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_INTM_TM_INVALID)
+#define NPI_VIR_TM_RES_INVALID (VIR_ERR_ST | VIR_TM_RES_INVALID)
+#define NPI_VIR_SID_VEC_INVALID(n) (VIR_ID_SHIFT(n) | \
+ VIR_ERR_ST | VIR_TM_RES_INVALID)
+
+/*
+ * Bit definition ([15:0] of the shared register
+ * used by the driver as locking mechanism.
+ * [1:0] lock state (RESET, FREE, BUSY)
+ * [3:2] function ID (owner)
+ * [11:4] Implementation specific states
+ * [15:12] Individual function state
+ */
+#define NPI_DEV_SR_LOCK_ST_RESET 0
+#define NPI_DEV_SR_LOCK_ST_FREE 1
+#define NPI_DEV_SR_LOCK_ST_BUSY 2
+
+#define NPI_DEV_SR_LOCK_ST_SHIFT 0
+#define NPI_DEV_SR_LOCK_ST_MASK 0x03
+#define NPI_DEV_SR_LOCK_FID_SHIFT 2
+#define NPI_DEV_SR_LOCK_FID_MASK 0x0C
+
+#define NPI_DEV_SR_IMPL_ST_SHIFT 4
+#define NPI_DEV_SR_IMPL_ST_MASK 0xfff0
+
+#define NPI_GET_LOCK_OWNER(sr) ((sr & NPI_DEV_SR_LOCK_FID_MASK) \
+ >> NPI_DEV_SR_LOCK_FID_SHIFT)
+#define NPI_GET_LOCK_ST(sr) (sr & NPI_DEV_SR_LOCK_ST_MASK)
+#define NPI_GET_LOCK_IMPL_ST(sr) ((sr & NPI_DEV_SR_IMPL_ST_MASK) \
+ >> NPI_DEV_SR_IMPL_ST_SHIFT)
+
+/*
+ * DMA channel binding definitions.
+ */
+#define DMA_BIND_VADDR_VALIDATE(fn, rn, id, status) \
+{ \
+ status = NPI_SUCCESS; \
+ if (!TXDMA_FUNC_VALID(fn)) { \
+ status = (NPI_FAILURE | NPI_VIR_BD_FUNC_INVALID(fn)); \
+ } else if (!SUBREGION_VALID(rn)) { \
+ status = (NPI_FAILURE | NPI_VIR_BD_REG_INVALID(rn)); \
+ } else if (!VIR_PAGE_INDEX_VALID(id)) { \
+ status = (NPI_FAILURE | NPI_VIR_BD_ID_INVALID(id)); \
+ } \
+}
+
+#define DMA_BIND_TX_VALIDATE(n, status) \
+{ \
+ status = NPI_SUCCESS; \
+ if (!TXDMA_CHANNEL_VALID(n)) { \
+ status = (NPI_FAILURE | NPI_VIR_BD_TXDMA_INVALID(n)); \
+ } \
+}
+
+#define DMA_BIND_RX_VALIDATE(n, status) \
+{ \
+ status = NPI_SUCCESS; \
+ if (!VRXDMA_CHANNEL_VALID(n)) { \
+ status = (NPI_FAILURE | NPI_VIR_BD_RXDMA_INVALID(n)); \
+ } \
+}
+
+#define DMA_BIND_STEP 8
+#define DMA_BIND_REG_OFFSET(fn, rn, id) (DMA_BIND_STEP * \
+ (fn * 2 * VIR_PAGE_INDEX_MAX + \
+ rn * VIR_PAGE_INDEX_MAX) + id)
+
+/*
+ * NPI defined data structure to program the DMA binding register.
+ */
+typedef struct _fzc_dma_bind {
+ uint8_t function_id; /* 0 to 3 */
+ uint8_t sub_vir_region; /* 0 or 1 */
+ uint8_t vir_index; /* 0 to 7 */
+ boolean_t tx_bind; /* set 1 to bind */
+ uint8_t tx_channel; /* hardware channel number (0 - 23) */
+ boolean_t rx_bind; /* set 1 to bind */
+ uint8_t rx_channel; /* hardware channel number (0 - 15) */
+} fzc_dma_bind_t, *p_fzc_dma_bind;
+
+/*
+ * Logical device definitions.
+ */
+#define LD_NUM_STEP 8
+#define LD_NUM_OFFSET(ld) (ld * LDG_NUM_STEP)
+#define LDG_NUM_STEP 8
+#define LDG_NUM_OFFSET(ldg) (ldg * LDG_NUM_STEP)
+#define LDGNUM_OFFSET(ldg) (ldg * LDG_NUM_STEP)
+#define LDSV_STEP 8192
+#define LDSVG_OFFSET(ldg) (ldg * LDSV_STEP)
+#define LDSV_OFFSET(ldv) (ldv * LDSV_STEP)
+
+#define LDSV_OFFSET_MASK(ld) \
+ (((ld < NXGE_MAC_LD_START) ? \
+ (LD_IM0_REG + LDSV_OFFSET(ld)) : \
+ (LD_IM1_REG + LDSV_OFFSET((ld - NXGE_MAC_LD_START))))); \
+
+#define LDG_SID_STEP 8
+#define LDG_SID_OFFSET(ldg) (ldg * LDG_SID_STEP)
+
+typedef enum {
+ LDF0,
+ LDF1
+} ldf_type_t;
+
+typedef enum {
+ VECTOR0,
+ VECTOR1,
+ VECTOR2
+} ldsv_type_t;
+
+/*
+ * Definitions for the system interrupt data.
+ */
+typedef struct _fzc_sid {
+ boolean_t niu;
+ uint8_t ldg;
+ uint8_t func;
+ uint8_t vector;
+} fzc_sid_t, *p_fzc_sid_t;
+
+/*
+ * Virtualization and Interrupt Prototypes.
+ */
+/*
+ * npi_dev_func_sr_init():
+ * This function is called to initialize the device function
+ * shared register (set the software implementation lock
+ * state to FREE).
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If initialization is complete successfully.
+ * (set sr bits to free).
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t npi_dev_func_sr_init(npi_handle_t);
+
+/*
+ * npi_dev_func_sr_lock_enter():
+ * This function is called to lock the function shared register
+ * by setting the lock state to busy.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If the function id can own the lock.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_SR_RESET
+ * VIR_SR_BUSY
+ * VIR_SR_INVALID
+ * VIR_TAS_BUSY
+ */
+npi_status_t npi_dev_func_sr_lock_enter(npi_handle_t);
+
+/*
+ * npi_dev_func_sr_lock_free():
+ * This function is called to free the function shared register
+ * by setting the lock state to free.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS - If the function id can free the lock.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_SR_NOTOWNER
+ * VIR_TAS_NOTREAD
+ */
+npi_status_t npi_dev_func_sr_lock_free(npi_handle_t);
+
+/*
+ * npi_dev_func_sr_funcid_get():
+ * This function is called to get the caller's function ID.
+ * (based on address bits [25:26] on read access.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear.) This function will write 0 to clear
+ * the TAS bit if we own it.
+ * Parameters:
+ * handle - NPI handle
+ * funcid_p - pointer to store the function id.
+ * Return:
+ * NPI_SUCCESS - If get function id is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t npi_dev_func_sr_funcid_get(npi_handle_t, uint8_t *);
+
+/*
+ * npi_dev_func_sr_sr_raw_get():
+ * This function is called to get the shared register value.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear if we own it.)
+ *
+ * Parameters:
+ * handle - NPI handle
+ * sr_p - pointer to store the shared value of this register.
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value get is complete successfully.
+ *
+ * Error:
+ */
+npi_status_t npi_dev_func_sr_sr_raw_get(npi_handle_t, uint16_t *);
+
+/*
+ * npi_dev_func_sr_sr_get():
+ * This function is called to get the shared register value.
+ * (After read, the TAS bit is always set to 1. Software needs
+ * to write 0 to clear if we own it.)
+ *
+ * Parameters:
+ * handle - NPI handle
+ * sr_p - pointer to store the shared value of this register.
+ * . this will get only non-lock, non-function id portion
+ * . of the register
+ *
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value get is complete successfully.
+ *
+ * Error:
+ */
+
+npi_status_t npi_dev_func_sr_sr_get(npi_handle_t, uint16_t *);
+
+/*
+ * npi_dev_func_sr_sr_get_set_clear():
+ * This function is called to set the shared register value.
+ * (Shared register must be read first. If tas bit is 0, then
+ * it implies that the software can proceed to set). After
+ * setting, tas bit will be cleared.
+ * Parameters:
+ * handle - NPI handle
+ * impl_sr - shared value to set (only the 8 bit
+ * implementation specific state info).
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value is set successfully.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t npi_dev_func_sr_sr_get_set_clear(npi_handle_t,
+ uint16_t);
+
+/*
+ * npi_dev_func_sr_sr_set_only():
+ * This function is called to only set the shared register value.
+ * Parameters:
+ * handle - NPI handle
+ * impl_sr - shared value to set.
+ *
+ * Return:
+ * NPI_SUCCESS - If shared value is set successfully.
+ *
+ * Error:
+ * NPI_FAILURE
+ * VIR_TAS_BUSY
+ */
+npi_status_t npi_dev_func_sr_sr_set_only(npi_handle_t, uint16_t);
+
+/*
+ * npi_dev_func_sr_busy():
+ * This function is called to see if we can own the device.
+ * It will not reset the tas bit.
+ * Parameters:
+ * handle - NPI handle
+ * busy_p - pointer to store busy flag.
+ * (B_TRUE: device is in use, B_FALSE: free).
+ * Return:
+ * NPI_SUCCESS - If tas bit is read successfully.
+ * Error:
+ */
+npi_status_t npi_dev_func_sr_busy(npi_handle_t, boolean_t *);
+
+/*
+ * npi_dev_func_sr_tas_get():
+ * This function is called to get the tas bit
+ * (after read, this bit is always set to 1, software write 0
+ * to clear it).
+ *
+ * Parameters:
+ * handle - NPI handle
+ * tas_p - pointer to store the tas value
+ *
+ * Return:
+ * NPI_SUCCESS - If tas value get is complete successfully.
+ * Error:
+ */
+npi_status_t npi_dev_func_sr_tas_get(npi_handle_t, uint8_t *);
+
+/*
+ * npi_fzc_mpc_set():
+ * This function is called to enable the write access
+ * to FZC region to function zero.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ */
+npi_status_t npi_fzc_mpc_set(npi_handle_t, boolean_t);
+
+/*
+ * npi_fzc_mpc_get():
+ * This function is called to get the access mode.
+ * Parameters:
+ * handle - NPI handle
+ * Return:
+ * NPI_SUCCESS -
+ *
+ */
+npi_status_t npi_fzc_mpc_get(npi_handle_t, boolean_t *);
+
+/*
+ * npi_fzc_dma_bind_set():
+ * This function is called to set DMA binding register.
+ * Parameters:
+ * handle - NPI handle
+ * dma_bind - NPI defined data structure that
+ * contains the tx/rx channel binding info.
+ * to set.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ *
+ */
+npi_status_t npi_fzc_dma_bind_set(npi_handle_t, fzc_dma_bind_t);
+
+/*
+ * npi_fzc_ldg_num_set():
+ * This function is called to set up a logical group number that
+ * a logical device belongs to.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device number (0 - 68)
+ * ldg - logical device group number (0 - 63)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ *
+ */
+npi_status_t npi_fzc_ldg_num_set(npi_handle_t, uint8_t, uint8_t);
+
+/*
+ * npi_fzc_ldg_num_get():
+ * This function is called to get the logical device group that
+ * a logical device belongs to.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device number (0 - 68)
+ * *ldg_p - pointer to store its group number.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_fzc_ldg_num_get(npi_handle_t, uint8_t,
+ uint8_t *);
+
+npi_status_t npi_ldsv_ldfs_get(npi_handle_t, uint8_t,
+ uint64_t *, uint64_t *, uint64_t *);
+/*
+ * npi_ldsv_get():
+ * This function is called to get device state vectors.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ldf_type - either LDF0 (0) or LDF1 (1)
+ * vector - vector type (0, 1 or 2)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_ldsv_get(npi_handle_t, uint8_t, ldsv_type_t,
+ uint64_t *);
+
+/*
+ * npi_ldsv_ld_get():
+ * This function is called to get the flag bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * ldf_type - either LDF0 (0) or LDF1 (1)
+ * vector - vector type (0, 1 or 2)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_ldsv_ld_get(npi_handle_t, uint8_t, uint8_t,
+ ldsv_type_t, ldf_type_t, boolean_t *);
+/*
+ * npi_ldsv_ld_ldf0_get():
+ * This function is called to get the ldf0 bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_ldsv_ld_ldf0_get(npi_handle_t, uint8_t, uint8_t,
+ boolean_t *);
+
+/*
+ * npi_ldsv_ld_ldf1_get():
+ * This function is called to get the ldf1 bit value of a device.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * ld - logical device (0 - 68)
+ * *ldf_p - pointer to store its flag bits.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_ldsv_ld_ldf1_get(npi_handle_t, uint8_t, uint8_t,
+ boolean_t *);
+/*
+ * npi_intr_mask_set():
+ * This function is called to select the mask bits for both ldf0 and ldf1.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device (0 - 68)
+ * ldf_mask - mask value to set (both ldf0 and ldf1).
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_intr_mask_set(npi_handle_t, uint8_t,
+ uint8_t);
+
+/*
+ * npi_intr_mask_get():
+ * This function is called to get the mask bits.
+ * Parameters:
+ * handle - NPI handle
+ * ld - logical device (0 - 68)
+ * ldf_mask - pointer to store mask bits info.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_intr_mask_get(npi_handle_t, uint8_t,
+ uint8_t *);
+
+/*
+ * npi_intr_ldg_mgmt_set():
+ * This function is called to set interrupt timer and arm bit.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * arm - B_TRUE (arm) B_FALSE (disable)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_intr_ldg_mgmt_set(npi_handle_t, uint8_t,
+ boolean_t, uint8_t);
+
+
+/*
+ * npi_intr_ldg_mgmt_timer_get():
+ * This function is called to get the timer counter
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * timer_p - pointer to store the timer counter.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_intr_ldg_mgmt_timer_get(npi_handle_t, uint8_t,
+ uint8_t *);
+
+/*
+ * npi_intr_ldg_mgmt_arm():
+ * This function is called to arm the group.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical device group (0 - 63)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_intr_ldg_mgmt_arm(npi_handle_t, uint8_t);
+
+/*
+ * npi_fzc_ldg_timer_res_set():
+ * This function is called to set the timer resolution.
+ * Parameters:
+ * handle - NPI handle
+ * res - timer resolution (# of system clocks)
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_fzc_ldg_timer_res_set(npi_handle_t, uint32_t);
+
+/*
+ * npi_fzc_ldg_timer_res_get():
+ * This function is called to get the timer resolution.
+ * Parameters:
+ * handle - NPI handle
+ * res_p - pointer to store the timer resolution.
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_fzc_ldg_timer_res_get(npi_handle_t, uint8_t *);
+
+/*
+ * npi_fzc_sid_set():
+ * This function is called to set the system interrupt data.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical group (0 - 63)
+ * sid - NPI defined data to set
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_fzc_sid_set(npi_handle_t, fzc_sid_t);
+
+/*
+ * npi_fzc_sid_get():
+ * This function is called to get the system interrupt data.
+ * Parameters:
+ * handle - NPI handle
+ * ldg - logical group (0 - 63)
+ * sid_p - NPI defined data to get
+ * Return:
+ * NPI_SUCCESS -
+ * Error:
+ * NPI_FAILURE
+ */
+npi_status_t npi_fzc_sid_get(npi_handle_t, p_fzc_sid_t);
+npi_status_t npi_fzc_sys_err_mask_set(npi_handle_t, uint64_t);
+npi_status_t npi_fzc_sys_err_stat_get(npi_handle_t,
+ p_sys_err_stat_t);
+npi_status_t npi_vir_dump_pio_fzc_regs_one(npi_handle_t);
+npi_status_t npi_vir_dump_ldgnum(npi_handle_t);
+npi_status_t npi_vir_dump_ldsv(npi_handle_t);
+npi_status_t npi_vir_dump_imask0(npi_handle_t);
+npi_status_t npi_vir_dump_sid(npi_handle_t);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_VIR_H */
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.c b/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.c
new file mode 100644
index 0000000000..72fdf14f19
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.c
@@ -0,0 +1,758 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_zcp.h>
+
+static int zcp_mem_read(npi_handle_t, uint16_t, uint8_t,
+ uint16_t, zcp_ram_unit_t *);
+static int zcp_mem_write(npi_handle_t, uint16_t, uint8_t,
+ uint32_t, uint16_t,
+ zcp_ram_unit_t *);
+
+npi_status_t
+npi_zcp_config(npi_handle_t handle, config_op_t op, zcp_config_t config)
+{
+ uint64_t val = 0;
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((config == 0) || (config & ~CFG_ZCP_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_ZCP_CONFIG_INVALID);
+ }
+
+ NXGE_REG_RD64(handle, ZCP_CONFIG_REG, &val);
+ if (op == ENABLE) {
+ if (config & CFG_ZCP)
+ val |= ZC_ENABLE;
+ if (config & CFG_ZCP_ECC_CHK)
+ val &= ~ECC_CHK_DIS;
+ if (config & CFG_ZCP_PAR_CHK)
+ val &= ~PAR_CHK_DIS;
+ if (config & CFG_ZCP_BUF_RESP)
+ val &= ~DIS_BUFF_RN;
+ if (config & CFG_ZCP_BUF_REQ)
+ val &= ~DIS_BUFF_RQ_IF;
+ } else {
+ if (config & CFG_ZCP)
+ val &= ~ZC_ENABLE;
+ if (config & CFG_ZCP_ECC_CHK)
+ val |= ECC_CHK_DIS;
+ if (config & CFG_ZCP_PAR_CHK)
+ val |= PAR_CHK_DIS;
+ if (config & CFG_ZCP_BUF_RESP)
+ val |= DIS_BUFF_RN;
+ if (config & CFG_ZCP_BUF_REQ)
+ val |= DIS_BUFF_RQ_IF;
+ }
+ NXGE_REG_WR64(handle, ZCP_CONFIG_REG, val);
+
+ break;
+ case INIT:
+ NXGE_REG_RD64(handle, ZCP_CONFIG_REG, &val);
+ val &= ((ZCP_DEBUG_SEL_MASK) | (RDMA_TH_MASK));
+ if (config & CFG_ZCP)
+ val |= ZC_ENABLE;
+ else
+ val &= ~ZC_ENABLE;
+ if (config & CFG_ZCP_ECC_CHK)
+ val &= ~ECC_CHK_DIS;
+ else
+ val |= ECC_CHK_DIS;
+ if (config & CFG_ZCP_PAR_CHK)
+ val &= ~PAR_CHK_DIS;
+ else
+ val |= PAR_CHK_DIS;
+ if (config & CFG_ZCP_BUF_RESP)
+ val &= ~DIS_BUFF_RN;
+ else
+ val |= DIS_BUFF_RN;
+ if (config & CFG_ZCP_BUF_REQ)
+ val &= DIS_BUFF_RQ_IF;
+ else
+ val |= DIS_BUFF_RQ_IF;
+ NXGE_REG_WR64(handle, ZCP_CONFIG_REG, val);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_config"
+ " Invalid Input: config <0x%x>",
+ config));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_iconfig(npi_handle_t handle, config_op_t op, zcp_iconfig_t iconfig)
+{
+ uint64_t val = 0;
+
+ switch (op) {
+ case ENABLE:
+ case DISABLE:
+ if ((iconfig == 0) || (iconfig & ~ICFG_ZCP_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_ZCP_CONFIG_INVALID);
+ }
+
+ NXGE_REG_RD64(handle, ZCP_INT_MASK_REG, &val);
+ if (op == ENABLE)
+ val |= iconfig;
+ else
+ val &= ~iconfig;
+ NXGE_REG_WR64(handle, ZCP_INT_MASK_REG, val);
+
+ break;
+
+ case INIT:
+ if ((iconfig & ~ICFG_ZCP_ALL) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_ZCP_CONFIG_INVALID);
+ }
+ val = (uint64_t)iconfig;
+ NXGE_REG_WR64(handle, ZCP_INT_MASK_REG, val);
+
+ break;
+ default:
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_iconfig"
+ " Invalid Input: iconfig <0x%x>",
+ iconfig));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_get_istatus(npi_handle_t handle, zcp_iconfig_t *istatus)
+{
+ uint64_t val;
+
+ NXGE_REG_RD64(handle, ZCP_INT_STAT_REG, &val);
+ *istatus = (uint32_t)val;
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_clear_istatus(npi_handle_t handle)
+{
+ uint64_t val;
+
+ val = (uint64_t)0xffff;
+ NXGE_REG_WR64(handle, ZCP_INT_STAT_REG, val);
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_zcp_set_dma_thresh(npi_handle_t handle, uint16_t dma_thres)
+{
+ uint64_t val = 0;
+
+ if ((dma_thres & ~RDMA_TH_BITS) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_set_dma_thresh"
+ " Invalid Input: dma_thres <0x%x>",
+ dma_thres));
+ return (NPI_FAILURE | NPI_ZCP_DMA_THRES_INVALID);
+ }
+
+ NXGE_REG_RD64(handle, ZCP_CONFIG_REG, &val);
+
+ val &= ~RDMA_TH_MASK;
+ val |= (dma_thres << RDMA_TH_SHIFT);
+
+ NXGE_REG_WR64(handle, ZCP_CONFIG_REG, val);
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_set_bam_region(npi_handle_t handle, zcp_buf_region_t region,
+ zcp_bam_region_reg_t *region_attr)
+{
+
+ if (!IS_VALID_BAM_REGION(region)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_set_bam_region"
+ " Invalid Input: region <0x%x>",
+ region));
+ return (NPI_FAILURE | ZCP_BAM_REGION_INVALID);
+ }
+
+ switch (region) {
+ case BAM_4BUF:
+ NXGE_REG_WR64(handle, ZCP_BAM4_RE_CTL_REG, region_attr->value);
+ break;
+ case BAM_8BUF:
+ NXGE_REG_WR64(handle, ZCP_BAM8_RE_CTL_REG, region_attr->value);
+ break;
+ case BAM_16BUF:
+ NXGE_REG_WR64(handle, ZCP_BAM16_RE_CTL_REG, region_attr->value);
+ break;
+ case BAM_32BUF:
+ NXGE_REG_WR64(handle, ZCP_BAM32_RE_CTL_REG, region_attr->value);
+ break;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_set_dst_region(npi_handle_t handle, zcp_buf_region_t region,
+ uint16_t row_idx)
+{
+ uint64_t val = 0;
+
+ if (!IS_VALID_BAM_REGION(region)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_set_dst_region"
+ " Invalid Input: region <0x%x>",
+ region));
+ return (NPI_FAILURE | NPI_ZCP_BAM_REGION_INVALID);
+ }
+
+ if ((row_idx & ~0x3FF) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_set_dst_region"
+ " Invalid Input: row_idx", row_idx));
+ return (NPI_FAILURE | NPI_ZCP_ROW_INDEX_INVALID);
+ }
+
+ val = (uint64_t)row_idx;
+
+ switch (region) {
+ case BAM_4BUF:
+ NXGE_REG_WR64(handle, ZCP_DST4_RE_CTL_REG, val);
+ break;
+ case BAM_8BUF:
+ NXGE_REG_WR64(handle, ZCP_DST8_RE_CTL_REG, val);
+ break;
+ case BAM_16BUF:
+ NXGE_REG_WR64(handle, ZCP_DST16_RE_CTL_REG, val);
+ break;
+ case BAM_32BUF:
+ NXGE_REG_WR64(handle, ZCP_DST32_RE_CTL_REG, val);
+ break;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_tt_static_entry(npi_handle_t handle, io_op_t op, uint16_t flow_id,
+ tte_sflow_attr_mask_t mask, tte_sflow_attr_t *sflow)
+{
+ uint32_t byte_en = 0;
+ tte_sflow_attr_t val;
+
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " Invalid Input: op <0x%x>",
+ op));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ if ((mask & TTE_SFLOW_ATTR_ALL) == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " Invalid Input: mask <0x%x>",
+ mask));
+ return (NPI_FAILURE | NPI_ZCP_SFLOW_ATTR_INVALID);
+ }
+
+ if ((flow_id & ~0x0FFF) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " Invalid Input: flow_id<0x%x>",
+ flow_id));
+ return (NPI_FAILURE | NPI_ZCP_FLOW_ID_INVALID);
+ }
+
+ if (zcp_mem_read(handle, flow_id, ZCP_RAM_SEL_TT_STATIC, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_READ_FAILED);
+ }
+
+ if (op == OP_SET) {
+ if (mask & TTE_RDC_TBL_OFF) {
+ val.qw0.bits.ldw.rdc_tbl_offset =
+ sflow->qw0.bits.ldw.rdc_tbl_offset;
+ byte_en |= TTE_RDC_TBL_SFLOW_BITS_EN;
+ }
+ if (mask & TTE_BUF_SIZE) {
+ val.qw0.bits.ldw.buf_size =
+ sflow->qw0.bits.ldw.buf_size;
+ byte_en |= TTE_BUF_SIZE_BITS_EN;
+ }
+ if (mask & TTE_NUM_BUF) {
+ val.qw0.bits.ldw.num_buf = sflow->qw0.bits.ldw.num_buf;
+ byte_en |= TTE_NUM_BUF_BITS_EN;
+ }
+ if (mask & TTE_ULP_END) {
+ val.qw0.bits.ldw.ulp_end = sflow->qw0.bits.ldw.ulp_end;
+ byte_en |= TTE_ULP_END_BITS_EN;
+ }
+ if (mask & TTE_ULP_END) {
+ val.qw1.bits.ldw.ulp_end = sflow->qw1.bits.ldw.ulp_end;
+ byte_en |= TTE_ULP_END_BITS_EN;
+ }
+ if (mask & TTE_ULP_END_EN) {
+ val.qw1.bits.ldw.ulp_end_en =
+ sflow->qw1.bits.ldw.ulp_end_en;
+ byte_en |= TTE_ULP_END_EN_BITS_EN;
+ }
+ if (mask & TTE_UNMAP_ALL_EN) {
+ val.qw1.bits.ldw.unmap_all_en =
+ sflow->qw1.bits.ldw.unmap_all_en;
+ byte_en |= TTE_UNMAP_ALL_EN;
+ }
+ if (mask & TTE_TMODE) {
+ val.qw1.bits.ldw.tmode = sflow->qw1.bits.ldw.tmode;
+ byte_en |= TTE_TMODE_BITS_EN;
+ }
+ if (mask & TTE_SKIP) {
+ val.qw1.bits.ldw.skip = sflow->qw1.bits.ldw.skip;
+ byte_en |= TTE_SKIP_BITS_EN;
+ }
+ if (mask & TTE_HBM_RING_BASE_ADDR) {
+ val.qw1.bits.ldw.ring_base =
+ sflow->qw1.bits.ldw.ring_base;
+ byte_en |= TTE_RING_BASE_ADDR_BITS_EN;
+ }
+ if (mask & TTE_HBM_RING_BASE_ADDR) {
+ val.qw2.bits.ldw.ring_base =
+ sflow->qw2.bits.ldw.ring_base;
+ byte_en |= TTE_RING_BASE_ADDR_BITS_EN;
+ }
+ if (mask & TTE_HBM_RING_SIZE) {
+ val.qw2.bits.ldw.ring_size =
+ sflow->qw2.bits.ldw.ring_size;
+ byte_en |= TTE_RING_SIZE_BITS_EN;
+ }
+ if (mask & TTE_HBM_BUSY) {
+ val.qw2.bits.ldw.busy = sflow->qw2.bits.ldw.busy;
+ byte_en |= TTE_BUSY_BITS_EN;
+ }
+ if (mask & TTE_HBM_TOQ) {
+ val.qw3.bits.ldw.toq = sflow->qw3.bits.ldw.toq;
+ byte_en |= TTE_TOQ_BITS_EN;
+ }
+
+ if (zcp_mem_write(handle, flow_id, ZCP_RAM_SEL_TT_STATIC,
+ byte_en, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_WRITE_FAILED);
+ }
+ } else {
+ sflow->qw0.value = val.qw0.value;
+ sflow->qw1.value = val.qw1.value;
+ sflow->qw2.value = val.qw2.value;
+ sflow->qw3.value = val.qw3.value;
+ sflow->qw4.value = val.qw4.value;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_tt_dynamic_entry(npi_handle_t handle, io_op_t op, uint16_t flow_id,
+ tte_dflow_attr_mask_t mask, tte_dflow_attr_t *dflow)
+{
+ uint32_t byte_en = 0;
+ tte_dflow_attr_t val;
+
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ if ((mask & TTE_DFLOW_ATTR_ALL) == 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " Invalid Input: mask <0x%x>",
+ mask));
+ return (NPI_FAILURE | NPI_ZCP_DFLOW_ATTR_INVALID);
+ }
+
+ if ((flow_id & ~0x0FFF) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " Invalid Input: flow_id <0x%x>",
+ flow_id));
+ return (NPI_FAILURE | NPI_ZCP_FLOW_ID_INVALID);
+ }
+
+ if (zcp_mem_read(handle, flow_id, ZCP_RAM_SEL_TT_DYNAMIC, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_READ_FAILED);
+ }
+
+ if (op == OP_SET) {
+
+ /* Get data read */
+ if (mask & TTE_MAPPED_IN) {
+ val.qw0.bits.ldw.mapped_in =
+ dflow->qw0.bits.ldw.mapped_in;
+ byte_en |= TTE_MAPPED_IN_BITS_EN;
+ }
+ if (mask & TTE_ANCHOR_SEQ) {
+ val.qw1.bits.ldw.anchor_seq =
+ dflow->qw1.bits.ldw.anchor_seq;
+ byte_en |= TTE_ANCHOR_SEQ_BITS_EN;
+ }
+ if (mask & TTE_ANCHOR_OFFSET) {
+ val.qw2.bits.ldw.anchor_offset =
+ dflow->qw2.bits.ldw.anchor_offset;
+ byte_en |= TTE_ANCHOR_OFFSET_BITS_EN;
+ }
+ if (mask & TTE_ANCHOR_BUFFER) {
+ val.qw2.bits.ldw.anchor_buf =
+ dflow->qw2.bits.ldw.anchor_buf;
+ byte_en |= TTE_ANCHOR_BUFFER_BITS_EN;
+ }
+ if (mask & TTE_ANCHOR_BUF_FLAG) {
+ val.qw2.bits.ldw.anchor_buf_flag =
+ dflow->qw2.bits.ldw.anchor_buf_flag;
+ byte_en |= TTE_ANCHOR_BUF_FLAG_BITS_EN;
+ }
+ if (mask & TTE_UNMAP_ON_LEFT) {
+ val.qw2.bits.ldw.unmap_on_left =
+ dflow->qw2.bits.ldw.unmap_on_left;
+ byte_en |= TTE_UNMAP_ON_LEFT_BITS_EN;
+ }
+ if (mask & TTE_ULP_END_REACHED) {
+ val.qw2.bits.ldw.ulp_end_reached =
+ dflow->qw2.bits.ldw.ulp_end_reached;
+ byte_en |= TTE_ULP_END_REACHED_BITS_EN;
+ }
+ if (mask & TTE_ERR_STAT) {
+ val.qw3.bits.ldw.err_stat =
+ dflow->qw3.bits.ldw.err_stat;
+ byte_en |= TTE_ERR_STAT_BITS_EN;
+ }
+ if (mask & TTE_HBM_WR_PTR) {
+ val.qw3.bits.ldw.wr_ptr = dflow->qw3.bits.ldw.wr_ptr;
+ byte_en |= TTE_WR_PTR_BITS_EN;
+ }
+ if (mask & TTE_HBM_HOQ) {
+ val.qw3.bits.ldw.hoq = dflow->qw3.bits.ldw.hoq;
+ byte_en |= TTE_HOQ_BITS_EN;
+ }
+ if (mask & TTE_HBM_PREFETCH_ON) {
+ val.qw3.bits.ldw.prefetch_on =
+ dflow->qw3.bits.ldw.prefetch_on;
+ byte_en |= TTE_PREFETCH_ON_BITS_EN;
+ }
+
+ if (zcp_mem_write(handle, flow_id, ZCP_RAM_SEL_TT_DYNAMIC,
+ byte_en, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_WRITE_FAILED);
+ }
+ } else {
+ dflow->qw0.value = val.qw0.value;
+ dflow->qw1.value = val.qw1.value;
+ dflow->qw2.value = val.qw2.value;
+ dflow->qw3.value = val.qw3.value;
+ dflow->qw4.value = val.qw4.value;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_tt_bam_entry(npi_handle_t handle, io_op_t op, uint16_t flow_id,
+ uint8_t bankn, uint8_t word_en, zcp_ram_unit_t *data)
+{
+ zcp_ram_unit_t val;
+
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_bam_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ if ((flow_id & ~0x0FFF) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_dynamic_entry"
+ " Invalid Input: flow_id <0x%x>",
+ flow_id));
+ return (NPI_FAILURE | NPI_ZCP_FLOW_ID_INVALID);
+ }
+
+ if (bankn >= MAX_BAM_BANKS) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_bam_entry"
+ " Invalid Input: bankn <0x%x>",
+ bankn));
+ return (NPI_FAILURE | NPI_ZCP_BAM_BANK_INVALID);
+ }
+
+ if ((word_en & ~0xF) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_bam_entry"
+ " Invalid Input: word_en <0x%x>",
+ word_en));
+ return (NPI_FAILURE | NPI_ZCP_BAM_WORD_EN_INVALID);
+ }
+
+ if (zcp_mem_read(handle, flow_id, ZCP_RAM_SEL_BAM0 + bankn, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_bam_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_READ_FAILED);
+ }
+
+ if (op == OP_SET) {
+ if (zcp_mem_write(handle, flow_id, ZCP_RAM_SEL_BAM0 + bankn,
+ word_en, NULL,
+ (zcp_ram_unit_t *)&val) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_bam_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_WRITE_FAILED);
+ }
+ } else {
+ data->w0 = val.w0;
+ data->w1 = val.w1;
+ data->w2 = val.w2;
+ data->w3 = val.w3;
+ }
+
+ return (NPI_SUCCESS);
+}
+
+npi_status_t
+npi_zcp_tt_cfifo_entry(npi_handle_t handle, io_op_t op, uint8_t portn,
+ uint16_t entryn, zcp_ram_unit_t *data)
+{
+ if ((op != OP_SET) && (op != OP_GET)) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_cfifo_entry"
+ " Invalid Input: op <0x%x>", op));
+ return (NPI_FAILURE | NPI_ZCP_OPCODE_INVALID);
+ }
+
+ if (portn > 3) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_cfifo_entry"
+ " Invalid Input: portn <%d>", portn));
+ return (NPI_FAILURE | NPI_ZCP_PORT_INVALID(portn));
+ }
+
+ if (op == OP_SET) {
+ if (zcp_mem_write(handle, NULL, ZCP_RAM_SEL_CFIFO0 + portn,
+ 0x1ffff, entryn, data) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_cfifo_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_WRITE_FAILED);
+ }
+ } else {
+ if (zcp_mem_read(handle, NULL, ZCP_RAM_SEL_CFIFO0 + portn,
+ entryn, data) != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_cfifo_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ NULL));
+ return (NPI_FAILURE | NPI_ZCP_MEM_READ_FAILED);
+ }
+ }
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_zcp_rest_cfifo_port(npi_handle_t handle, uint8_t port)
+{
+ uint64_t offset = ZCP_RESET_CFIFO_REG;
+ zcp_reset_cfifo_t cfifo_reg;
+ NXGE_REG_RD64(handle, offset, &cfifo_reg.value);
+ cfifo_reg.value &= ZCP_RESET_CFIFO_MASK;
+
+ switch (port) {
+ case 0:
+ cfifo_reg.bits.ldw.reset_cfifo0 = 1;
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ cfifo_reg.bits.ldw.reset_cfifo0 = 0;
+
+ break;
+ case 1:
+ cfifo_reg.bits.ldw.reset_cfifo1 = 1;
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ cfifo_reg.bits.ldw.reset_cfifo1 = 0;
+ break;
+ case 2:
+ cfifo_reg.bits.ldw.reset_cfifo2 = 1;
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ cfifo_reg.bits.ldw.reset_cfifo2 = 0;
+ break;
+ case 3:
+ cfifo_reg.bits.ldw.reset_cfifo3 = 1;
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ cfifo_reg.bits.ldw.reset_cfifo3 = 0;
+ break;
+ default:
+ break;
+ }
+
+ NXGE_DELAY(ZCP_CFIFIO_RESET_WAIT);
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+
+ return (NPI_SUCCESS);
+}
+
+
+npi_status_t
+npi_zcp_rest_cfifo_all(npi_handle_t handle)
+{
+ uint64_t offset = ZCP_RESET_CFIFO_REG;
+ zcp_reset_cfifo_t cfifo_reg;
+
+ cfifo_reg.value = ZCP_RESET_CFIFO_MASK;
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ cfifo_reg.value = 0;
+ NXGE_DELAY(ZCP_CFIFIO_RESET_WAIT);
+ NXGE_REG_WR64(handle, offset, cfifo_reg.value);
+ return (NPI_SUCCESS);
+}
+
+static int
+zcp_mem_read(npi_handle_t handle, uint16_t flow_id, uint8_t ram_sel,
+ uint16_t cfifo_entryn, zcp_ram_unit_t *val)
+{
+ zcp_ram_access_t ram_ctl;
+
+ ram_ctl.value = 0;
+ ram_ctl.bits.ldw.ram_sel = ram_sel;
+ ram_ctl.bits.ldw.zcfid = flow_id;
+ ram_ctl.bits.ldw.rdwr = ZCP_RAM_RD;
+ ram_ctl.bits.ldw.cfifo = cfifo_entryn;
+
+ /* Wait for RAM ready to be read */
+ ZCP_WAIT_RAM_READY(handle, ram_ctl.value);
+ if (ram_ctl.bits.ldw.busy != 0) {
+ NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
+ " npi_zcp_tt_static_entry"
+ " HW Error: ZCP_RAM_ACC <0x%x>",
+ ram_ctl.value));
+ return (-1);
+ }
+
+ /* Read from RAM */
+ NXGE_REG_WR64(handle, ZCP_RAM_ACC_REG, ram_ctl.value);
+
+ /* Wait for RAM read done */
+ ZCP_WAIT_RAM_READY(handle, ram_ctl.value);
+ if (ram_ctl.bits.ldw.busy != 0)
+ return (-1);
+
+ /* Get data */
+ NXGE_REG_RD64(handle, ZCP_RAM_DATA0_REG, &val->w0);
+ NXGE_REG_RD64(handle, ZCP_RAM_DATA1_REG, &val->w1);
+ NXGE_REG_RD64(handle, ZCP_RAM_DATA2_REG, &val->w2);
+ NXGE_REG_RD64(handle, ZCP_RAM_DATA3_REG, &val->w3);
+ NXGE_REG_RD64(handle, ZCP_RAM_DATA4_REG, &val->w4);
+
+ return (0);
+}
+
+static int
+zcp_mem_write(npi_handle_t handle, uint16_t flow_id, uint8_t ram_sel,
+ uint32_t byte_en, uint16_t cfifo_entryn, zcp_ram_unit_t *val)
+{
+ zcp_ram_access_t ram_ctl;
+ zcp_ram_benable_t ram_en;
+
+ ram_ctl.value = 0;
+ ram_ctl.bits.ldw.ram_sel = ram_sel;
+ ram_ctl.bits.ldw.zcfid = flow_id;
+ ram_ctl.bits.ldw.rdwr = ZCP_RAM_WR;
+ ram_en.bits.ldw.be = byte_en;
+ ram_ctl.bits.ldw.cfifo = cfifo_entryn;
+
+ /* Setup data */
+ NXGE_REG_WR64(handle, ZCP_RAM_DATA0_REG, val->w0);
+ NXGE_REG_WR64(handle, ZCP_RAM_DATA1_REG, val->w1);
+ NXGE_REG_WR64(handle, ZCP_RAM_DATA2_REG, val->w2);
+ NXGE_REG_WR64(handle, ZCP_RAM_DATA3_REG, val->w3);
+ NXGE_REG_WR64(handle, ZCP_RAM_DATA4_REG, val->w4);
+
+ /* Set byte mask */
+ NXGE_REG_WR64(handle, ZCP_RAM_BE_REG, ram_en.value);
+
+ /* Write to RAM */
+ NXGE_REG_WR64(handle, ZCP_RAM_ACC_REG, ram_ctl.value);
+
+ /* Wait for RAM write complete */
+ ZCP_WAIT_RAM_READY(handle, ram_ctl.value);
+ if (ram_ctl.bits.ldw.busy != 0)
+ return (-1);
+
+ return (0);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.h b/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.h
new file mode 100644
index 0000000000..25c7337fca
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/npi/npi_zcp.h
@@ -0,0 +1,187 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _NPI_ZCP_H
+#define _NPI_ZCP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi.h>
+#include <nxge_zcp_hw.h>
+
+typedef enum zcp_buf_region_e {
+ BAM_4BUF = 1,
+ BAM_8BUF = 2,
+ BAM_16BUF = 3,
+ BAM_32BUF = 4
+} zcp_buf_region_t;
+
+typedef enum zcp_config_e {
+ CFG_ZCP = 0x01,
+ CFG_ZCP_ECC_CHK = 0x02,
+ CFG_ZCP_PAR_CHK = 0x04,
+ CFG_ZCP_BUF_RESP = 0x08,
+ CFG_ZCP_BUF_REQ = 0x10,
+ CFG_ZCP_ALL = 0x1F
+} zcp_config_t;
+
+typedef enum zcp_iconfig_e {
+ ICFG_ZCP_RRFIFO_UNDERRUN = RRFIFO_UNDERRUN,
+ ICFG_ZCP_RRFIFO_OVERRUN = RRFIFO_OVERRUN,
+ ICFG_ZCP_RSPFIFO_UNCORR_ERR = RSPFIFO_UNCORR_ERR,
+ ICFG_ZCP_BUFFER_OVERFLOW = BUFFER_OVERFLOW,
+ ICFG_ZCP_STAT_TBL_PERR = STAT_TBL_PERR,
+ ICFG_ZCP_DYN_TBL_PERR = BUF_DYN_TBL_PERR,
+ ICFG_ZCP_BUF_TBL_PERR = BUF_TBL_PERR,
+ ICFG_ZCP_TT_PROGRAM_ERR = TT_PROGRAM_ERR,
+ ICFG_ZCP_RSP_TT_INDEX_ERR = RSP_TT_INDEX_ERR,
+ ICFG_ZCP_SLV_TT_INDEX_ERR = SLV_TT_INDEX_ERR,
+ ICFG_ZCP_TT_INDEX_ERR = ZCP_TT_INDEX_ERR,
+ ICFG_ZCP_CFIFO_ECC3 = CFIFO_ECC3,
+ ICFG_ZCP_CFIFO_ECC2 = CFIFO_ECC2,
+ ICFG_ZCP_CFIFO_ECC1 = CFIFO_ECC1,
+ ICFG_ZCP_CFIFO_ECC0 = CFIFO_ECC0,
+ ICFG_ZCP_ALL = (RRFIFO_UNDERRUN | RRFIFO_OVERRUN |
+ RSPFIFO_UNCORR_ERR | STAT_TBL_PERR |
+ BUF_DYN_TBL_PERR | BUF_TBL_PERR |
+ TT_PROGRAM_ERR | RSP_TT_INDEX_ERR |
+ SLV_TT_INDEX_ERR | ZCP_TT_INDEX_ERR |
+ CFIFO_ECC3 | CFIFO_ECC2 | CFIFO_ECC1 |
+ CFIFO_ECC0 | BUFFER_OVERFLOW)
+} zcp_iconfig_t;
+
+typedef enum tte_sflow_attr_mask_e {
+ TTE_RDC_TBL_OFF = 0x0001,
+ TTE_BUF_SIZE = 0x0002,
+ TTE_NUM_BUF = 0x0004,
+ TTE_ULP_END = 0x0008,
+ TTE_ULP_END_EN = 0x0010,
+ TTE_UNMAP_ALL_EN = 0x0020,
+ TTE_TMODE = 0x0040,
+ TTE_SKIP = 0x0080,
+ TTE_HBM_RING_BASE_ADDR = 0x0100,
+ TTE_HBM_RING_SIZE = 0x0200,
+ TTE_HBM_BUSY = 0x0400,
+ TTE_HBM_TOQ = 0x0800,
+ TTE_SFLOW_ATTR_ALL = 0x0FFF
+} tte_sflow_attr_mask_t;
+
+typedef enum tte_dflow_attr_mask_e {
+ TTE_MAPPED_IN = 0x0001,
+ TTE_ANCHOR_SEQ = 0x0002,
+ TTE_ANCHOR_OFFSET = 0x0004,
+ TTE_ANCHOR_BUFFER = 0x0008,
+ TTE_ANCHOR_BUF_FLAG = 0x0010,
+ TTE_UNMAP_ON_LEFT = 0x0020,
+ TTE_ULP_END_REACHED = 0x0040,
+ TTE_ERR_STAT = 0x0080,
+ TTE_HBM_WR_PTR = 0x0100,
+ TTE_HBM_HOQ = 0x0200,
+ TTE_HBM_PREFETCH_ON = 0x0400,
+ TTE_DFLOW_ATTR_ALL = 0x07FF
+} tte_dflow_attr_mask_t;
+
+#define IS_VALID_BAM_REGION(region)\
+ ((region == BAM_4BUF) || (region == BAM_8BUF) ||\
+ (region == BAM_16BUF) || (region == BAM_32BUF))
+
+#define ZCP_WAIT_RAM_READY(handle, val) {\
+ uint32_t cnt = MAX_PIO_RETRIES;\
+ do {\
+ NXGE_REG_RD64(handle, ZCP_RAM_ACC_REG, &val);\
+ cnt--;\
+ } while ((ram_ctl.bits.ldw.busy != 0) && (cnt > 0));\
+}
+
+#define ZCP_DMA_THRES_INVALID 0x10
+#define ZCP_BAM_REGION_INVALID 0x11
+#define ZCP_ROW_INDEX_INVALID 0x12
+#define ZCP_SFLOW_ATTR_INVALID 0x13
+#define ZCP_DFLOW_ATTR_INVALID 0x14
+#define ZCP_FLOW_ID_INVALID 0x15
+#define ZCP_BAM_BANK_INVALID 0x16
+#define ZCP_BAM_WORD_EN_INVALID 0x17
+
+#define NPI_ZCP_OPCODE_INVALID ((ZCP_BLK_ID << 8) | OPCODE_INVALID)
+#define NPI_ZCP_CONFIG_INVALID ((ZCP_BLK_ID << 8) | CONFIG_INVALID)
+#define NPI_ZCP_DMA_THRES_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_DMA_THRES_INVALID)
+#define NPI_ZCP_BAM_REGION_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_BAM_REGION_INVALID)
+#define NPI_ZCP_ROW_INDEX_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_ROW_INDEX_INVALID)
+#define NPI_ZCP_SFLOW_ATTR_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_SFLOW_ATTR_INVALID)
+#define NPI_ZCP_DFLOW_ATTR_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_DFLOW_ATTR_INVALID)
+#define NPI_ZCP_FLOW_ID_INVALID ((ZCP_BLK_ID << 8) |\
+ ZCP_FLOW_ID_INVALID)
+#define NPI_ZCP_MEM_WRITE_FAILED ((ZCP_BLK_ID << 8) | WRITE_FAILED)
+#define NPI_ZCP_MEM_READ_FAILED ((ZCP_BLK_ID << 8) | READ_FAILED)
+#define NPI_ZCP_BAM_BANK_INVALID ((ZCP_BLK_ID << 8) |\
+ (ZCP_BAM_BANK_INVALID))
+#define NPI_ZCP_BAM_WORD_EN_INVALID ((ZCP_BLK_ID << 8) |\
+ (ZCP_BAM_WORD_EN_INVALID))
+#define NPI_ZCP_PORT_INVALID(portn) ((ZCP_BLK_ID << 8) | PORT_INVALID |\
+ (portn << 12))
+
+/* ZCP HW NPI Prototypes */
+npi_status_t npi_zcp_config(npi_handle_t, config_op_t,
+ zcp_config_t);
+npi_status_t npi_zcp_iconfig(npi_handle_t, config_op_t,
+ zcp_iconfig_t);
+npi_status_t npi_zcp_get_istatus(npi_handle_t, zcp_iconfig_t *);
+npi_status_t npi_zcp_clear_istatus(npi_handle_t);
+npi_status_t npi_zcp_set_dma_thresh(npi_handle_t, uint16_t);
+npi_status_t npi_zcp_set_bam_region(npi_handle_t,
+ zcp_buf_region_t,
+ zcp_bam_region_reg_t *);
+npi_status_t npi_zcp_set_sdt_region(npi_handle_t,
+ zcp_buf_region_t, uint16_t);
+npi_status_t npi_zcp_tt_static_entry(npi_handle_t, io_op_t,
+ uint16_t, tte_sflow_attr_mask_t,
+ tte_sflow_attr_t *);
+npi_status_t npi_zcp_tt_dynamic_entry(npi_handle_t, io_op_t,
+ uint16_t, tte_dflow_attr_mask_t,
+ tte_dflow_attr_t *);
+npi_status_t npi_zcp_tt_bam_entry(npi_handle_t, io_op_t,
+ uint16_t, uint8_t,
+ uint8_t, zcp_ram_unit_t *);
+npi_status_t npi_zcp_tt_cfifo_entry(npi_handle_t, io_op_t,
+ uint8_t, uint16_t,
+ zcp_ram_unit_t *);
+
+npi_status_t npi_zcp_rest_cfifo_port(npi_handle_t, uint8_t);
+npi_status_t npi_zcp_rest_cfifo_all(npi_handle_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NPI_ZCP_H */
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_classify.c b/usr/src/uts/sun4v/io/nxge/nxge_classify.c
new file mode 100644
index 0000000000..bec07b9b2f
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_classify.c
@@ -0,0 +1,208 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_fflp.h>
+#include <nxge_defs.h>
+#include <nxge_fflp.h>
+#include <nxge_flow.h>
+#include <nxge_impl.h>
+#include <nxge_common.h>
+
+/*
+ * Globals: tunable parameters (/etc/system or adb)
+ *
+ */
+/* 0f90 */
+int nxge_tcam_class_enable = 0;
+int nxge_tcam_lookup_enable = 0;
+int nxge_flow_dist_enable = NXGE_CLASS_FLOW_USE_DST_PORT |
+ NXGE_CLASS_FLOW_USE_SRC_PORT | NXGE_CLASS_FLOW_USE_IPDST |
+ NXGE_CLASS_FLOW_USE_IPSRC | NXGE_CLASS_FLOW_USE_PROTO |
+ NXGE_CLASS_FLOW_USE_PORTNUM;
+
+/*
+ * Bit mapped
+ * 0x80000000: Drop
+ * 0x0000: NO TCAM Lookup Needed
+ * 0x0001: TCAM Lookup Needed with Dest Addr (IPv6)
+ * 0x0003: TCAM Lookup Needed with SRC Addr (IPv6)
+ * 0x0010: use MAC Port
+ * 0x0020: use L2DA
+ * 0x0040: use VLAN
+ * 0x0080: use proto
+ * 0x0100: use IP src addr
+ * 0x0200: use IP dest addr
+ * 0x0400: use Src Port
+ * 0x0800: use Dest Port
+ * 0x0fff: enable all options for IPv6 (with src addr)
+ * 0x0ffd: enable all options for IPv6 (with dest addr)
+ * 0x0fff: enable all options for IPv4
+ * 0x0ffd: enable all options for IPv4
+ *
+ */
+
+/*
+ * the default is to distribute as function of:
+ * protocol
+ * ip src address
+ * ip dest address
+ * src port
+ * dest port
+ *
+ * 0x0f80
+ *
+ */
+
+int nxge_tcp4_class = NXGE_CLASS_FLOW_USE_DST_PORT |
+ NXGE_CLASS_FLOW_USE_SRC_PORT | NXGE_CLASS_FLOW_USE_IPDST |
+ NXGE_CLASS_FLOW_USE_IPSRC | NXGE_CLASS_FLOW_USE_PROTO |
+ NXGE_CLASS_FLOW_USE_PORTNUM;
+
+int nxge_udp4_class = NXGE_CLASS_FLOW_USE_DST_PORT |
+ NXGE_CLASS_FLOW_USE_SRC_PORT | NXGE_CLASS_FLOW_USE_IPDST |
+ NXGE_CLASS_FLOW_USE_IPSRC | NXGE_CLASS_FLOW_USE_PROTO |
+ NXGE_CLASS_FLOW_USE_PORTNUM;
+
+int nxge_ah4_class = 0x0f90;
+int nxge_sctp4_class = 0x0f90;
+int nxge_tcp6_class = 0x0f90;
+int nxge_udp6_class = 0x0f90;
+int nxge_ah6_class = 0x0f90;
+int nxge_sctp6_class = 0xf90;
+uint32_t nxge_fflp_init_h1 = 0xffffffff;
+uint32_t nxge_fflp_init_h2 = 0xffff;
+
+uint64_t class_quick_config_distribute [NXGE_CLASS_CONFIG_PARAMS] = {
+ 0xffffffffULL, /* h1_init */
+ 0xffffULL, /* h2_init */
+ 0x0, /* cfg_ether_usr1 */
+ 0x0, /* cfg_ether_usr2 */
+ 0x0, /* cfg_ip_usr4 */
+ 0x0, /* cfg_ip_usr5 */
+ 0x0, /* cfg_ip_usr6 */
+ 0x0, /* cfg_ip_usr7 */
+ 0x0, /* opt_ip_usr4 */
+ 0x0, /* opt_ip_usr5 */
+ 0x0, /* opt_ip_usr6 */
+ 0x0, /* opt_ip_usr7 */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_tcp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_udp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_ah */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_sctp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_tcp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_udp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_ah */
+ NXGE_CLASS_FLOW_GEN_SERVER /* opt_ipv6_sctp */
+};
+
+uint64_t class_quick_config_web_server [NXGE_CLASS_CONFIG_PARAMS] = {
+ 0xffffffffULL, /* h1_init */
+ 0xffffULL, /* h2_init */
+ 0x0, /* cfg_ether_usr1 */
+ 0x0, /* cfg_ether_usr2 */
+ 0x0, /* cfg_ip_usr4 */
+ 0x0, /* cfg_ip_usr5 */
+ 0x0, /* cfg_ip_usr6 */
+ 0x0, /* cfg_ip_usr7 */
+ 0x0, /* opt_ip_usr4 */
+ 0x0, /* opt_ip_usr5 */
+ 0x0, /* opt_ip_usr6 */
+ 0x0, /* opt_ip_usr7 */
+ NXGE_CLASS_FLOW_WEB_SERVER, /* opt_ipv4_tcp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_udp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_ah */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv4_sctp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_tcp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_udp */
+ NXGE_CLASS_FLOW_GEN_SERVER, /* opt_ipv6_ah */
+ NXGE_CLASS_FLOW_GEN_SERVER /* opt_ipv6_sctp */
+};
+
+
+nxge_status_t
+nxge_classify_init(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ status = nxge_classify_init_sw(nxgep);
+ if (status != NXGE_OK)
+ return (status);
+ status = nxge_set_hw_classify_config(nxgep);
+ if (status != NXGE_OK)
+ return (status);
+
+ status = nxge_classify_init_hw(nxgep);
+ if (status != NXGE_OK)
+ return (status);
+
+ return (NXGE_OK);
+}
+
+/* ARGSUSED */
+uint64_t
+nxge_classify_get_cfg_value(p_nxge_t nxgep, uint8_t cfg_type,
+ uint8_t cfg_param)
+{
+ uint64_t cfg_value;
+ if (cfg_param >= NXGE_CLASS_CONFIG_PARAMS)
+ return (-1);
+ switch (cfg_type) {
+ case CFG_L3_WEB:
+ cfg_value = class_quick_config_web_server[cfg_param];
+ break;
+ case CFG_L3_DISTRIBUTE:
+ default:
+ cfg_value = class_quick_config_distribute[cfg_param];
+ break;
+ }
+ return (cfg_value);
+
+}
+
+
+nxge_status_t
+nxge_set_hw_classify_config(p_nxge_t nxgep)
+{
+ p_nxge_dma_pt_cfg_t p_all_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_get_hw_classify_config"));
+
+ /* Get mac rdc table info from HW/Prom/.conf etc ...... */
+ /* for now, get it from dma configs */
+ p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
+
+ /*
+ * classify_init needs to call first.
+ */
+ nxgep->class_config.mac_rdcgrp = p_cfgp->def_mac_rxdma_grpid;
+ nxgep->class_config.mcast_rdcgrp = p_cfgp->def_mac_rxdma_grpid;
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "<== nxge_get_hw_classify_config"));
+
+ return (NXGE_OK);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_espc.c b/usr/src/uts/sun4v/io/nxge/nxge_espc.c
new file mode 100644
index 0000000000..346a572c4d
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_espc.c
@@ -0,0 +1,218 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nxge_impl.h>
+#include <nxge_mac.h>
+#include <npi_espc.h>
+#include <nxge_espc.h>
+
+static void
+nxge_espc_get_next_mac_addr(uint8_t *, uint8_t, struct ether_addr *);
+
+static void
+nxge_espc_get_next_mac_addr(uint8_t *st_mac, uint8_t nxt_cnt,
+ struct ether_addr *final_mac)
+{
+ uint64_t mac[ETHERADDRL];
+ uint64_t mac_addr = 0;
+ int i, j;
+
+ for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
+ mac[j] = st_mac[i];
+ mac_addr |= (mac[j] << (j*8));
+ }
+
+ mac_addr += nxt_cnt;
+
+ final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
+ final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
+ final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
+ final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
+ final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
+ final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
+}
+
+nxge_status_t
+nxge_espc_mac_addrs_get(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ npi_status_t npi_status = NPI_SUCCESS;
+ uint8_t port_num = nxgep->mac.portnum;
+ npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ uint8_t mac_addr[ETHERADDRL];
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_espc_mac_addr_get, port[%d]",
+ port_num));
+
+ npi_status = npi_espc_mac_addr_get(handle, mac_addr);
+ if (npi_status != NPI_SUCCESS) {
+ status = (NXGE_ERROR | npi_status);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_espc_mac_addr_get, port[%d] failed",
+ port_num));
+ goto exit;
+ }
+
+ nxge_espc_get_next_mac_addr(mac_addr, port_num, &nxgep->factaddr);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Got MAC Addr: %2x:%2x:%2x:%2x:%2x%:%2x%c \n",
+ mac_addr[0], mac_addr[1],
+ mac_addr[2], mac_addr[3],
+ mac_addr[4], mac_addr[5]));
+
+exit:
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_mac_addr_get, "
+ "status [0x%x]", status));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_espc_num_macs_get(p_nxge_t nxgep, uint8_t *nmacs)
+{
+ nxge_status_t status = NXGE_OK;
+ npi_status_t npi_status = NPI_SUCCESS;
+ npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_num_macs_get"));
+
+ npi_status = npi_espc_num_macs_get(handle, nmacs);
+ if (npi_status != NPI_SUCCESS) {
+ status = (NXGE_ERROR | npi_status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_num_macs_get, "
+ "status [0x%x]", status));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_espc_num_ports_get(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ npi_status_t npi_status = NPI_SUCCESS;
+ npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ uint8_t nports = 0;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_num_ports_get"));
+
+ npi_status = npi_espc_num_ports_get(handle, &nports);
+ if (npi_status != NPI_SUCCESS) {
+ status = (NXGE_ERROR | npi_status);
+ }
+ nxgep->nports = nports;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " nxge_espc_num_ports_get "
+ "ports [0x%x]", nports));
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_num_ports_get, "
+ "status [0x%x]", status));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_espc_phy_type_get(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ npi_status_t npi_status = NPI_SUCCESS;
+ npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ uint8_t port_num = nxgep->mac.portnum;
+ uint8_t phy_type;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_phy_type_get, port[%d]",
+ port_num));
+
+ npi_status = npi_espc_port_phy_type_get(handle, &phy_type,
+ port_num);
+ if (npi_status != NPI_SUCCESS) {
+ status = (NXGE_ERROR | npi_status);
+ goto exit;
+ }
+
+ switch (phy_type) {
+ case ESC_PHY_10G_FIBER:
+ nxgep->mac.portmode = PORT_10G_FIBER;
+ nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
+ cmn_err(CE_NOTE, "!SPROM Read phy type 10G Fiber \n");
+ break;
+ case ESC_PHY_10G_COPPER:
+ nxgep->mac.portmode = PORT_10G_COPPER;
+ nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
+ cmn_err(CE_NOTE, "!SPROM Read phy type 10G Copper \n");
+
+ break;
+ case ESC_PHY_1G_FIBER:
+ nxgep->mac.portmode = PORT_1G_FIBER;
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ cmn_err(CE_NOTE, "!SPROM Read phy type 1G Fiber \n");
+
+ break;
+ case ESC_PHY_1G_COPPER:
+ nxgep->mac.portmode = PORT_1G_COPPER;
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ cmn_err(CE_NOTE, "!SPROM Read phy type 1G Copper \n");
+
+ break;
+ case ESC_PHY_NONE:
+ status = NXGE_ERROR;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_espc_phy_type_get:"
+ "No phy type set"));
+ break;
+ default:
+ status = NXGE_ERROR;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_espc_phy_type_get: "
+ "Unknown phy type [%d]", phy_type));
+ break;
+ }
+
+exit:
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_espc_phy_type_get, "
+ "status [0x%x]", status));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_espc_max_frame_sz_get(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ npi_status_t npi_status = NPI_SUCCESS;
+ npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_espc_max_frame_sz_get"));
+
+ npi_status = npi_espc_max_frame_get(handle, &nxgep->mac.maxframesize);
+ if (npi_status != NPI_SUCCESS) {
+ status = (NXGE_ERROR | npi_status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " nxge_espc_max_frame_sz_get, "
+ "status [0x%x]", status));
+
+ return (status);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_fflp.c b/usr/src/uts/sun4v/io/nxge/nxge_fflp.c
new file mode 100644
index 0000000000..4efaf488a4
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_fflp.c
@@ -0,0 +1,2261 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <npi_fflp.h>
+#include <npi_mac.h>
+#include <nxge_defs.h>
+#include <nxge_flow.h>
+#include <nxge_fflp.h>
+#include <nxge_impl.h>
+#include <nxge_fflp_hash.h>
+#include <nxge_common.h>
+
+
+/* function prototypes */
+
+static nxge_status_t nxge_fflp_vlan_tbl_clear_all(p_nxge_t);
+static nxge_status_t nxge_fflp_tcam_invalidate_all(p_nxge_t);
+static nxge_status_t nxge_fflp_tcam_init(p_nxge_t);
+static nxge_status_t nxge_fflp_fcram_invalidate_all(p_nxge_t);
+static nxge_status_t nxge_fflp_fcram_init(p_nxge_t);
+static int nxge_flow_need_hash_lookup(p_nxge_t, flow_resource_t *);
+
+static void nxge_fill_tcam_entry_tcp(p_nxge_t, flow_spec_t *,
+ tcam_entry_t *);
+static void nxge_fill_tcam_entry_udp(p_nxge_t,
+ flow_spec_t *,
+ tcam_entry_t *);
+static void nxge_fill_tcam_entry_sctp(p_nxge_t,
+ flow_spec_t *,
+ tcam_entry_t *);
+
+static void nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t, flow_spec_t *,
+ tcam_entry_t *);
+
+static void nxge_fill_tcam_entry_udp_ipv6(p_nxge_t,
+ flow_spec_t *,
+ tcam_entry_t *);
+
+static void nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t,
+ flow_spec_t *,
+ tcam_entry_t *);
+
+static uint8_t nxge_get_rdc_offset(p_nxge_t, uint8_t, intptr_t);
+static uint8_t nxge_get_rdc_group(p_nxge_t, uint8_t, intptr_t);
+
+static tcam_location_t nxge_get_tcam_location(p_nxge_t, uint8_t);
+
+
+/* functions used outside this file */
+nxge_status_t nxge_fflp_config_vlan_table(p_nxge_t, uint16_t);
+nxge_status_t nxge_fflp_ip_class_config_all(p_nxge_t);
+nxge_status_t nxge_add_flow(p_nxge_t, flow_resource_t *);
+void nxge_handle_tcam_fragment_bug(p_nxge_t);
+nxge_status_t nxge_add_tcam_entry(p_nxge_t, flow_resource_t *);
+nxge_status_t nxge_add_fcram_entry(p_nxge_t, flow_resource_t *);
+nxge_status_t nxge_flow_get_hash(p_nxge_t, flow_resource_t *,
+ uint32_t *, uint16_t *);
+
+nxge_status_t nxge_classify_exit_sw(p_nxge_t);
+
+nxge_status_t
+nxge_tcam_dump_entry(p_nxge_t nxgep, uint32_t location)
+{
+ tcam_entry_t tcam_rdptr;
+ uint64_t asc_ram = 0;
+ npi_handle_t handle;
+ npi_status_t status;
+
+ handle = nxgep->npi_reg_handle;
+
+ bzero((char *)&tcam_rdptr, sizeof (struct tcam_entry));
+ status = npi_fflp_tcam_entry_read(handle, (tcam_location_t)location,
+ (struct tcam_entry *)&tcam_rdptr);
+ if (status & NPI_FAILURE) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_tcam_dump_entry:"
+ " tcam read failed at location %d ",
+ location));
+ return (NXGE_ERROR);
+ }
+
+ status = npi_fflp_tcam_asc_ram_entry_read(handle,
+ (tcam_location_t)location, &asc_ram);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "location %x\n"
+ " key: %llx %llx %llx %llx \n"
+ " mask: %llx %llx %llx %llx \n"
+ " ASC RAM %llx \n", location,
+ tcam_rdptr.key0, tcam_rdptr.key1,
+ tcam_rdptr.key2, tcam_rdptr.key3,
+ tcam_rdptr.mask0, tcam_rdptr.mask1,
+ tcam_rdptr.mask2, tcam_rdptr.mask3,
+ asc_ram));
+ return (NXGE_OK);
+}
+
+void
+nxge_get_tcam(p_nxge_t nxgep, p_mblk_t mp)
+{
+
+ uint32_t tcam_loc;
+ int *lptr;
+ int location;
+
+ uint32_t start_location = 0;
+ uint32_t stop_location = nxgep->classifier.tcam_size;
+ lptr = (int *)mp->b_rptr;
+ location = *lptr;
+
+ if ((location >= nxgep->classifier.tcam_size) || (location < -1)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_tcam_dump: Invalid location %d \n",
+ location));
+ return;
+ }
+ if (location == -1) {
+ start_location = 0;
+ stop_location = nxgep->classifier.tcam_size;
+ } else {
+ start_location = location;
+ stop_location = location +1;
+ }
+ for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
+ (void) nxge_tcam_dump_entry(nxgep, tcam_loc);
+
+}
+
+
+/*
+ * nxge_fflp_vlan_table_invalidate_all
+ * invalidates the vlan RDC table entries.
+ * INPUT
+ * nxge soft state data structure
+ * Return
+ * NXGE_OK
+ * NXGE_ERROR
+ *
+ */
+static nxge_status_t
+nxge_fflp_vlan_tbl_clear_all(p_nxge_t nxgep)
+{
+ vlan_id_t vlan_id;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_vlan_tbl_clear_all "));
+ handle = nxgep->npi_reg_handle;
+ for (vlan_id = start; vlan_id < stop; vlan_id++) {
+ rs = npi_fflp_cfg_vlan_table_clear(handle, vlan_id);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "VLAN Table invalidate failed for vlan id %d ",
+ vlan_id));
+ return (NXGE_ERROR | rs);
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_vlan_tbl_clear_all "));
+
+ return (NXGE_OK);
+}
+
+
+
+/*
+ * The following functions are used by other modules to init
+ * the fflp module.
+ * these functions are the basic API used to init
+ * the fflp modules (tcam, fcram etc ......)
+ *
+ * The TCAM search future would be disabled by default.
+ */
+
+static nxge_status_t
+nxge_fflp_tcam_init(p_nxge_t nxgep)
+{
+
+ uint8_t access_ratio;
+ tcam_class_t class;
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_tcam_init"));
+ handle = nxgep->npi_reg_handle;
+
+ rs = npi_fflp_cfg_tcam_disable(handle);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed TCAM Disable\n"));
+ return (NXGE_ERROR | rs);
+ }
+
+ access_ratio = nxgep->param_arr[param_tcam_access_ratio].value;
+ rs = npi_fflp_cfg_tcam_access(handle, access_ratio);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed TCAM Access cfg\n"));
+ return (NXGE_ERROR | rs);
+ }
+
+/* disable configurable classes */
+/* disable the configurable ethernet classes; */
+ for (class = TCAM_CLASS_ETYPE_1;
+ class <= TCAM_CLASS_ETYPE_2; class++) {
+ rs = npi_fflp_cfg_enet_usr_cls_disable(handle, class);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "TCAM USR Ether Class"
+ "config failed."));
+ return (NXGE_ERROR | rs);
+ }
+ }
+
+ /* disable the configurable ip classes; */
+ for (class = TCAM_CLASS_IP_USER_4;
+ class <= TCAM_CLASS_IP_USER_7; class++) {
+ rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "TCAM USR IP Class"
+ "cnfg failed."));
+ return (NXGE_ERROR | rs);
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_tcam_init"));
+
+ return (NXGE_OK);
+}
+
+
+/*
+ * nxge_fflp_tcam_invalidate_all
+ * invalidates all the tcam entries.
+ * INPUT
+ * nxge soft state data structure
+ * Return
+ * NXGE_OK
+ * NXGE_ERROR
+ *
+ */
+static nxge_status_t
+nxge_fflp_tcam_invalidate_all(p_nxge_t nxgep)
+{
+ uint16_t location;
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+ uint16_t start = 0, stop = nxgep->classifier.tcam_size;
+ p_nxge_hw_list_t hw_p;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "==> nxge_fflp_tcam_invalidate_all"));
+ handle = nxgep->npi_reg_handle;
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_tcam_invalidate_all:"
+ " common hardware not set",
+ nxgep->niu_type));
+ return (NXGE_ERROR);
+ }
+ MUTEX_ENTER(&hw_p->nxge_tcam_lock);
+ for (location = start; location < stop; location++) {
+ rs = npi_fflp_tcam_entry_invalidate(handle, location);
+ if (rs != NPI_SUCCESS) {
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "TCAM invalidate failed at loc %d ",
+ location));
+ return (NXGE_ERROR | rs);
+ }
+ }
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "<== nxge_fflp_tcam_invalidate_all"));
+ return (NXGE_OK);
+}
+
+/*
+ * nxge_fflp_fcram_entry_invalidate_all
+ * invalidates all the FCRAM entries.
+ * INPUT
+ * nxge soft state data structure
+ * Return
+ * NXGE_OK
+ * NXGE_ERROR
+ *
+ */
+static nxge_status_t
+nxge_fflp_fcram_invalidate_all(p_nxge_t nxgep)
+
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ part_id_t pid = 0;
+ uint8_t base_mask, base_reloc;
+ fcram_entry_t fc;
+ uint32_t location;
+ uint32_t increment, last_location;
+
+/*
+ * (1) configure and enable partition 0 with no relocation
+ * (2) Assume the FCRAM is used as IPv4 exact match entry cells
+ * (3) Invalidate these cells by clearing the valid bit in
+ * the subareas 0 and 4
+ * (4) disable the partition
+ *
+ */
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_invalidate_all"));
+
+ base_mask = base_reloc = 0x0;
+ handle = nxgep->npi_reg_handle;
+ rs = npi_fflp_cfg_fcram_partition(handle, pid, base_mask, base_reloc);
+
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed partition cfg\n"));
+ return (NXGE_ERROR | rs);
+ }
+
+ rs = npi_fflp_cfg_fcram_partition_disable(handle, pid);
+
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed partition enable\n"));
+ return (NXGE_ERROR | rs);
+ }
+
+ fc.dreg[0].value = 0;
+ fc.hash_hdr_valid = 0;
+ fc.hash_hdr_ext = 1; /* specify as IPV4 exact match entry */
+ increment = sizeof (hash_ipv4_t);
+ last_location = FCRAM_SIZE * 0x40;
+
+ for (location = 0; location < last_location; location += increment) {
+ rs = npi_fflp_fcram_subarea_write(handle, pid,
+ location,
+ fc.value[0]);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed write"
+ "at location %x ",
+ location));
+ return (NXGE_ERROR | rs);
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_invalidate_all"));
+
+ return (NXGE_OK);
+
+}
+
+
+static nxge_status_t
+nxge_fflp_fcram_init(p_nxge_t nxgep)
+
+{
+ fflp_fcram_output_drive_t strength;
+ fflp_fcram_qs_t qs;
+ npi_status_t rs = NPI_SUCCESS;
+ uint8_t access_ratio;
+ int partition;
+ npi_handle_t handle;
+ uint32_t min_time, max_time, sys_time;
+
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_init"));
+
+/*
+ * for these we need to get the recommended values from Michael
+ */
+ min_time = FCRAM_REFRESH_DEFAULT_MIN_TIME;
+ max_time = FCRAM_REFRESH_DEFAULT_MAX_TIME;
+ sys_time = FCRAM_REFRESH_DEFAULT_SYS_TIME;
+ handle = nxgep->npi_reg_handle;
+ strength = FCRAM_OUTDR_NORMAL;
+ qs = FCRAM_QS_MODE_QS;
+ rs = npi_fflp_cfg_fcram_reset(handle, strength, qs);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Reset. "));
+ return (NXGE_ERROR | rs);
+ }
+
+ access_ratio = nxgep->param_arr[param_fcram_access_ratio].value;
+ rs = npi_fflp_cfg_fcram_access(handle, access_ratio);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Access ratio"
+ "configuration \n"));
+ return (NXGE_ERROR | rs);
+ }
+
+ rs = npi_fflp_cfg_fcram_refresh_time(handle, min_time,
+ max_time, sys_time);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed FCRAM refresh cfg"));
+ return (NXGE_ERROR);
+ }
+
+ /* disable all the partitions until explicitly enabled */
+ for (partition = 0; partition < FFLP_FCRAM_MAX_PARTITION; partition++) {
+ rs = npi_fflp_cfg_fcram_partition_disable(handle,
+ partition);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed FCRAM partition"
+ " enable for partition %d ",
+ partition));
+ return (NXGE_ERROR | rs);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_init"));
+
+ return (NXGE_OK);
+
+}
+
+
+nxge_status_t
+nxge_logical_mac_assign_rdc_table(p_nxge_t nxgep, uint8_t alt_mac)
+{
+
+ npi_status_t rs = NPI_SUCCESS;
+ hostinfo_t mac_rdc;
+ npi_handle_t handle;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+
+ if (p_class_cfgp->mac_host_info[alt_mac].flag == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_logical_mac_assign_rdc_table"
+ " unconfigured alt MAC addr %d ",
+ alt_mac));
+ return (NXGE_ERROR);
+ }
+
+ handle = nxgep->npi_reg_handle;
+ mac_rdc.value = 0;
+ mac_rdc.bits.w0.rdc_tbl_num =
+ p_class_cfgp->mac_host_info[alt_mac].rdctbl;
+ mac_rdc.bits.w0.mac_pref = p_class_cfgp->mac_host_info[alt_mac].mpr_npr;
+
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num, alt_mac, &mac_rdc);
+
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed Assign RDC table"));
+ return (NXGE_ERROR | rs);
+ }
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_main_mac_assign_rdc_table(p_nxge_t nxgep)
+{
+
+ npi_status_t rs = NPI_SUCCESS;
+ hostinfo_t mac_rdc;
+ npi_handle_t handle;
+
+ handle = nxgep->npi_reg_handle;
+ mac_rdc.value = 0;
+ mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mac_rdcgrp;
+ mac_rdc.bits.w0.mac_pref = 1;
+ switch (nxgep->function_num) {
+ case 0:
+ case 1:
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num,
+ XMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
+ break;
+ case 2:
+ case 3:
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num,
+ BMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
+ break;
+ default:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed Assign RDC table (invalid funcion #)"));
+ return (NXGE_ERROR);
+ }
+
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed Assign RDC table"));
+ return (NXGE_ERROR | rs);
+ }
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_multicast_mac_assign_rdc_table(p_nxge_t nxgep)
+{
+
+ npi_status_t rs = NPI_SUCCESS;
+ hostinfo_t mac_rdc;
+ npi_handle_t handle;
+
+ handle = nxgep->npi_reg_handle;
+ mac_rdc.value = 0;
+ mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mcast_rdcgrp;
+ mac_rdc.bits.w0.mac_pref = 1;
+ switch (nxgep->function_num) {
+ case 0:
+ case 1:
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num,
+ XMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
+ break;
+ case 2:
+ case 3:
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num,
+ BMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
+ break;
+ default:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed Assign RDC table (invalid funcion #)"));
+ return (NXGE_ERROR);
+ }
+
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed Assign RDC table"));
+ return (NXGE_ERROR | rs);
+ }
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_init_hostinfo(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ status = nxge_multicast_mac_assign_rdc_table(nxgep);
+ status = nxge_main_mac_assign_rdc_table(nxgep);
+ return (status);
+}
+
+
+nxge_status_t
+nxge_fflp_hw_reset(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_hw_reset"));
+
+
+ if (nxgep->niu_type == NEPTUNE) {
+ status = nxge_fflp_fcram_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " failed FCRAM init. "));
+ return (status);
+ }
+ }
+
+
+ status = nxge_fflp_tcam_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed TCAM init."));
+ return (status);
+ }
+
+ handle = nxgep->npi_reg_handle;
+ rs = npi_fflp_cfg_llcsnap_enable(handle);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed LLCSNAP enable. "));
+ return (NXGE_ERROR | rs);
+ }
+
+ rs = npi_fflp_cfg_cam_errorcheck_disable(handle);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed CAM Error Check enable. "));
+ return (NXGE_ERROR | rs);
+ }
+
+/* init the hash generators */
+
+ rs = npi_fflp_cfg_hash_h1poly(handle, 0);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed H1 Poly Init. "));
+ return (NXGE_ERROR | rs);
+ }
+
+ rs = npi_fflp_cfg_hash_h2poly(handle, 0);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed H2 Poly Init. "));
+ return (NXGE_ERROR | rs);
+ }
+
+
+/* invalidate TCAM entries */
+ status = nxge_fflp_tcam_invalidate_all(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed TCAM Entry Invalidate. "));
+ return (status);
+ }
+
+/* invalidate FCRAM entries */
+ if (nxgep->niu_type == NEPTUNE) {
+ status = nxge_fflp_fcram_invalidate_all(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed FCRAM Entry Invalidate. "));
+ return (status);
+ }
+ }
+
+
+/* invalidate VLAN RDC tables */
+
+ status = nxge_fflp_vlan_tbl_clear_all(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "failed VLAN Table Invalidate. "));
+ return (status);
+ }
+
+ nxgep->classifier.state |= NXGE_FFLP_HW_RESET;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_hw_reset"));
+
+ return (NXGE_OK);
+
+}
+
+
+nxge_status_t
+nxge_cfg_ip_cls_flow_key(p_nxge_t nxgep, tcam_class_t l3_class,
+ uint32_t class_config)
+{
+ flow_key_cfg_t fcfg;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key"));
+ handle = nxgep->npi_reg_handle;
+ bzero(&fcfg, sizeof (flow_key_cfg_t));
+
+ if (class_config & NXGE_CLASS_FLOW_USE_PROTO)
+ fcfg.use_proto = 1;
+ if (class_config & NXGE_CLASS_FLOW_USE_DST_PORT)
+ fcfg.use_dport = 1;
+ if (class_config & NXGE_CLASS_FLOW_USE_SRC_PORT)
+ fcfg.use_sport = 1;
+ if (class_config & NXGE_CLASS_FLOW_USE_IPDST)
+ fcfg.use_daddr = 1;
+ if (class_config & NXGE_CLASS_FLOW_USE_IPSRC)
+ fcfg.use_saddr = 1;
+ if (class_config & NXGE_CLASS_FLOW_USE_VLAN)
+ fcfg.use_vlan = 1;
+
+ if (class_config & NXGE_CLASS_FLOW_USE_L2DA)
+ fcfg.use_l2da = 1;
+
+ if (class_config & NXGE_CLASS_FLOW_USE_PORTNUM)
+ fcfg.use_portnum = 1;
+
+ fcfg.ip_opts_exist = 0;
+
+ rs = npi_fflp_cfg_ip_cls_flow_key(handle, l3_class, &fcfg);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
+ " opt %x for class %d failed ",
+ class_config, l3_class));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_cfg_ip_cls_flow_key"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_cfg_ip_cls_flow_key_get(p_nxge_t nxgep, tcam_class_t l3_class,
+ uint32_t *class_config)
+{
+ flow_key_cfg_t fcfg;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ uint32_t ccfg = 0;
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key_get"));
+ handle = nxgep->npi_reg_handle;
+ bzero(&fcfg, sizeof (flow_key_cfg_t));
+
+ rs = npi_fflp_cfg_ip_cls_flow_key_get(handle, l3_class, &fcfg);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
+ " opt %x for class %d failed ",
+ class_config, l3_class));
+ return (NXGE_ERROR | rs);
+ }
+
+ if (fcfg.use_proto)
+ ccfg |= NXGE_CLASS_FLOW_USE_PROTO;
+
+ if (fcfg.use_dport)
+ ccfg |= NXGE_CLASS_FLOW_USE_DST_PORT;
+
+ if (fcfg.use_sport)
+ ccfg |= NXGE_CLASS_FLOW_USE_SRC_PORT;
+
+ if (fcfg.use_daddr)
+ ccfg |= NXGE_CLASS_FLOW_USE_IPDST;
+
+ if (fcfg.use_saddr)
+ ccfg |= NXGE_CLASS_FLOW_USE_IPSRC;
+
+ if (fcfg.use_vlan)
+ ccfg |= NXGE_CLASS_FLOW_USE_VLAN;
+
+ if (fcfg.use_l2da)
+ ccfg |= NXGE_CLASS_FLOW_USE_L2DA;
+
+ if (fcfg.use_portnum)
+ ccfg |= NXGE_CLASS_FLOW_USE_PORTNUM;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " nxge_cfg_ip_cls_flow_key_get %x", ccfg));
+ *class_config = ccfg;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_cfg_ip_cls_flow_key_get"));
+ return (NXGE_OK);
+}
+
+
+static nxge_status_t
+nxge_cfg_tcam_ip_class_get(p_nxge_t nxgep, tcam_class_t class,
+ uint32_t *class_config)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ tcam_key_cfg_t cfg;
+ npi_handle_t handle;
+ uint32_t ccfg = 0;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
+
+ bzero(&cfg, sizeof (tcam_key_cfg_t));
+ handle = nxgep->npi_reg_handle;
+
+ rs = npi_fflp_cfg_ip_cls_tcam_key_get(handle, class, &cfg);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
+ " opt %x for class %d failed ",
+ class_config, class));
+ return (NXGE_ERROR | rs);
+ }
+ if (cfg.discard)
+ ccfg |= NXGE_CLASS_DISCARD;
+
+ if (cfg.lookup_enable)
+ ccfg |= NXGE_CLASS_TCAM_LOOKUP;
+
+ if (cfg.use_ip_daddr)
+ ccfg |= NXGE_CLASS_TCAM_USE_SRC_ADDR;
+
+ *class_config = ccfg;
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_cfg_tcam_ip_class %x", ccfg));
+ return (NXGE_OK);
+}
+
+
+static nxge_status_t
+nxge_cfg_tcam_ip_class(p_nxge_t nxgep, tcam_class_t class,
+ uint32_t class_config)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ tcam_key_cfg_t cfg;
+ npi_handle_t handle;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ p_class_cfgp->class_cfg[class] = class_config;
+
+ bzero(&cfg, sizeof (tcam_key_cfg_t));
+ handle = nxgep->npi_reg_handle;
+ cfg.discard = 0;
+ cfg.lookup_enable = 0;
+ cfg.use_ip_daddr = 0;
+ if (class_config & NXGE_CLASS_DISCARD)
+ cfg.discard = 1;
+ if (class_config & NXGE_CLASS_TCAM_LOOKUP)
+ cfg.lookup_enable = 1;
+ if (class_config & NXGE_CLASS_TCAM_USE_SRC_ADDR)
+ cfg.use_ip_daddr = 1;
+
+ rs = npi_fflp_cfg_ip_cls_tcam_key(handle, class, &cfg);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
+ " opt %x for class %d failed ",
+ class_config, class));
+ return (NXGE_ERROR | rs);
+ }
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_fflp_set_hash1(p_nxge_t nxgep, uint32_t h1)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h1"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ p_class_cfgp->init_h1 = h1;
+ handle = nxgep->npi_reg_handle;
+ rs = npi_fflp_cfg_hash_h1poly(handle, h1);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_fflp_init_h1"
+ " %x failed ",
+ h1));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h1"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_set_hash2(p_nxge_t nxgep, uint16_t h2)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h2"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ p_class_cfgp->init_h2 = h2;
+
+ handle = nxgep->npi_reg_handle;
+ rs = npi_fflp_cfg_hash_h2poly(handle, h2);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_fflp_init_h2"
+ " %x failed ",
+ h2));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h2"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_classify_init_sw(p_nxge_t nxgep)
+{
+ int alloc_size;
+ nxge_classify_t *classify_ptr;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_sw"));
+ classify_ptr = &nxgep->classifier;
+
+ if (classify_ptr->state & NXGE_FFLP_SW_INIT) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_classify_init_sw already init"));
+ return (NXGE_OK);
+ }
+
+ /* Init SW structures */
+
+ classify_ptr->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
+ /* init data structures, based on HW type */
+ if (nxgep->niu_type == NEPTUNE) {
+ classify_ptr->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
+ /*
+ * check if fcram based classification is required
+ * and init the flow storage
+ */
+ }
+
+ alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
+ classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL);
+
+ /* Init defaults */
+ /*
+ * add hacks required for HW shortcomings
+ * for example, code to handle fragmented packets
+ */
+
+ nxge_init_h1_table();
+ nxge_crc_ccitt_init();
+ nxgep->classifier.tcam_location = nxgep->function_num;
+ nxgep->classifier.fragment_bug = 1;
+ classify_ptr->state |= NXGE_FFLP_SW_INIT;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_sw"));
+
+ return (NXGE_OK);
+
+}
+
+
+
+nxge_status_t
+nxge_classify_exit_sw(p_nxge_t nxgep)
+{
+ int alloc_size;
+ nxge_classify_t *classify_ptr;
+ int fsize;
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_exit_sw"));
+ classify_ptr = &nxgep->classifier;
+
+ fsize = sizeof (tcam_flow_spec_t);
+ if (classify_ptr->tcam_entries) {
+ alloc_size = fsize * classify_ptr->tcam_size;
+ KMEM_FREE((void*)classify_ptr->tcam_entries, alloc_size);
+ }
+
+ nxgep->classifier.state = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_exit_sw"));
+
+ return (NXGE_OK);
+
+}
+
+
+
+/*
+ * Figures out the location where the TCAM entry is
+ * to be inserted.
+ *
+ * The current implementation is just a place holder and it
+ * returns the next tcam location.
+ * The real location determining algorithm would consider
+ * the priority, partition etc ... before deciding which
+ * location to insert.
+ *
+ */
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static tcam_location_t
+nxge_get_tcam_location(p_nxge_t nxgep, uint8_t class)
+{
+ tcam_location_t location;
+ location = nxgep->classifier.tcam_location;
+ nxgep->classifier.tcam_location = (location + nxgep->nports) %
+ nxgep->classifier.tcam_size;
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_get_tcam_location: location %d next %d \n",
+ location, nxgep->classifier.tcam_location));
+ return (location);
+}
+
+
+/*
+ * Figures out the RDC Group for the entry
+ *
+ * The current implementation is just a place holder and it
+ * returns 0.
+ * The real location determining algorithm would consider
+ * the partition etc ... before deciding w
+ *
+ */
+#ifdef lint
+/* ARGSUSED */
+#endif
+static uint8_t
+nxge_get_rdc_group(p_nxge_t nxgep, uint8_t class, intptr_t cookie)
+{
+ int use_port_rdc_grp = 0;
+ uint8_t rdc_grp = 0;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[use_port_rdc_grp];
+ rdc_grp = p_cfgp->start_rdc_grpid;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_get_rdc_group: grp 0x%x real_grp %x grpp $%p\n",
+ cookie, rdc_grp, rdc_grp_p));
+ return (rdc_grp);
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static uint8_t
+nxge_get_rdc_offset(p_nxge_t nxgep, uint8_t class, intptr_t cookie)
+{
+ return ((uint8_t)cookie);
+}
+
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static void
+nxge_fill_tcam_entry_udp(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+ udpip4_spec_t *fspec_key;
+ udpip4_spec_t *fspec_mask;
+
+ fspec_key = (udpip4_spec_t *)&flow_spec->uh.udpip4spec;
+ fspec_mask = (udpip4_spec_t *)&flow_spec->um.udpip4spec;
+
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
+
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+
+ TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
+ tcam_ptr->ip4_class_mask,
+ TCAM_CLASS_UDP_IPV4);
+
+ TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
+ tcam_ptr->ip4_proto_mask,
+ IPPROTO_UDP);
+
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static void
+nxge_fill_tcam_entry_udp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+ udpip6_spec_t *fspec_key;
+ udpip6_spec_t *fspec_mask;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ fspec_key = (udpip6_spec_t *)&flow_spec->uh.udpip6spec;
+ fspec_mask = (udpip6_spec_t *)&flow_spec->um.udpip6spec;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
+ NXGE_CLASS_TCAM_USE_SRC_ADDR) {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
+ } else {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
+ }
+
+ TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
+ tcam_ptr->ip6_class_mask, TCAM_CLASS_UDP_IPV6);
+
+
+ TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
+ tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_UDP);
+
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+
+static void
+nxge_fill_tcam_entry_tcp(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+
+ tcpip4_spec_t *fspec_key;
+ tcpip4_spec_t *fspec_mask;
+
+ fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
+ fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
+
+
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
+
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+
+ TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
+ tcam_ptr->ip4_class_mask, TCAM_CLASS_TCP_IPV4);
+
+ TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
+ tcam_ptr->ip4_proto_mask, IPPROTO_TCP);
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static void
+nxge_fill_tcam_entry_sctp(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+
+ tcpip4_spec_t *fspec_key;
+ tcpip4_spec_t *fspec_mask;
+
+ fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
+ fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
+
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
+ TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
+
+ TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
+ tcam_ptr->ip4_class_mask, TCAM_CLASS_SCTP_IPV4);
+
+ TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
+ tcam_ptr->ip4_proto_mask, IPPROTO_SCTP);
+
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+}
+
+
+
+static void
+nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+
+ tcpip6_spec_t *fspec_key;
+ tcpip6_spec_t *fspec_mask;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
+ fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
+
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
+ NXGE_CLASS_TCAM_USE_SRC_ADDR) {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
+
+ } else {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
+ }
+
+ TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
+ tcam_ptr->ip6_class_mask, TCAM_CLASS_TCP_IPV6);
+
+
+ TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
+ tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_TCP);
+
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+
+}
+
+
+static void
+nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
+ tcam_entry_t *tcam_ptr)
+{
+
+ tcpip6_spec_t *fspec_key;
+ tcpip6_spec_t *fspec_mask;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
+ fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+
+ if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
+ NXGE_CLASS_TCAM_USE_SRC_ADDR) {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
+
+ } else {
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
+ TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
+ }
+
+ TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
+ tcam_ptr->ip6_class_mask, TCAM_CLASS_SCTP_IPV6);
+
+
+ TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
+ tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_SCTP);
+
+
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
+ fspec_key->pdst, fspec_key->psrc);
+ TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
+ fspec_mask->pdst, fspec_mask->psrc);
+
+
+}
+
+
+nxge_status_t
+nxge_flow_get_hash(p_nxge_t nxgep, flow_resource_t *flow_res,
+ uint32_t *H1, uint16_t *H2)
+{
+
+
+ intptr_t channel_cookie;
+ intptr_t flow_cookie;
+ flow_spec_t *flow_spec;
+ uint32_t class_cfg;
+ flow_template_t ft;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ int ft_size = sizeof (flow_template_t);
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_flow_get_hash"));
+
+ flow_spec = (flow_spec_t *)&flow_res->flow_spec;
+ flow_cookie = flow_res->flow_cookie;
+ channel_cookie = flow_res->channel_cookie;
+#ifdef lint
+ flow_cookie = flow_cookie;
+ channel_cookie = channel_cookie;
+#endif
+ bzero((char *)&ft, ft_size);
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ switch (flow_spec->flow_type) {
+ case FSPEC_TCPIP4:
+ class_cfg =
+ p_class_cfgp->class_cfg[TCAM_CLASS_TCP_IPV4];
+ if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
+ ft.ip_proto = IPPROTO_TCP;
+ if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
+ ft.ip4_saddr =
+ flow_res->flow_spec.uh.tcpip4spec.ip4src;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
+ ft.ip4_daddr =
+ flow_res->flow_spec.uh.tcpip4spec.ip4dst;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
+ ft.ip_src_port =
+ flow_res->flow_spec.uh.tcpip4spec.psrc;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
+ ft.ip_dst_port =
+ flow_res->flow_spec.uh.tcpip4spec.pdst;
+
+ break;
+
+ case FSPEC_UDPIP4:
+ class_cfg =
+ p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV4];
+ if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
+ ft.ip_proto = IPPROTO_UDP;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
+ ft.ip4_saddr =
+ flow_res->flow_spec.uh.udpip4spec.ip4src;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
+ ft.ip4_daddr =
+ flow_res->flow_spec.uh.udpip4spec.ip4dst;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
+ ft.ip_src_port =
+ flow_res->flow_spec.uh.udpip4spec.psrc;
+
+ if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
+ ft.ip_dst_port =
+ flow_res->flow_spec.uh.udpip4spec.pdst;
+
+ break;
+
+ default:
+ return (NXGE_ERROR);
+ }
+
+ *H1 = nxge_compute_h1(p_class_cfgp->init_h1,
+ (uint32_t *)&ft, ft_size) & 0xfffff;
+ *H2 = nxge_compute_h2(p_class_cfgp->init_h2,
+ (uint8_t *)&ft, ft_size);
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_flow_get_hash"));
+ return (NXGE_OK);
+}
+
+/* ARGSUSED */
+nxge_status_t
+nxge_add_fcram_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
+{
+
+ uint32_t H1;
+ uint16_t H2;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_fcram_entry"));
+ status = nxge_flow_get_hash(nxgep, flow_res, &H1, &H2);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_add_fcram_entry failed "));
+ return (status);
+ }
+
+ /* add code to find rdc grp */
+ /* add code to determine the action */
+ /* Determine type of match (exact, optimistic etc ...) */
+ /* Compose hash entry */
+ /* add hash entry */
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_fcram_entry"));
+ return (NXGE_OK);
+}
+
+
+/*
+ * Already decided this flow goes into the tcam
+ */
+
+nxge_status_t
+nxge_add_tcam_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
+{
+
+ npi_handle_t handle;
+ intptr_t channel_cookie;
+ intptr_t flow_cookie;
+ flow_spec_t *flow_spec;
+ npi_status_t rs = NPI_SUCCESS;
+ tcam_entry_t tcam_ptr;
+ tcam_location_t location = 0;
+ uint8_t offset, rdc_grp;
+ p_nxge_hw_list_t hw_p;
+
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_tcam_entry"));
+ handle = nxgep->npi_reg_handle;
+
+ bzero((void*)&tcam_ptr, sizeof (tcam_entry_t));
+ flow_spec = (flow_spec_t *)&flow_res->flow_spec;
+ flow_cookie = flow_res->flow_cookie;
+ channel_cookie = flow_res->channel_cookie;
+
+ switch (flow_spec->flow_type) {
+ case FSPEC_TCPIP4:
+
+ nxge_fill_tcam_entry_tcp(nxgep, flow_spec, &tcam_ptr);
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_TCP_IPV4);
+ rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV4,
+ flow_cookie);
+ offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV4,
+ channel_cookie);
+
+ break;
+
+
+ case FSPEC_UDPIP4:
+
+ nxge_fill_tcam_entry_udp(nxgep, flow_spec, &tcam_ptr);
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_UDP_IPV4);
+ rdc_grp = nxge_get_rdc_group(nxgep,
+ TCAM_CLASS_UDP_IPV4,
+ flow_cookie);
+ offset = nxge_get_rdc_offset(nxgep,
+ TCAM_CLASS_UDP_IPV4,
+ channel_cookie);
+
+ break;
+
+
+ case FSPEC_TCPIP6:
+
+ nxge_fill_tcam_entry_tcp_ipv6(nxgep,
+ flow_spec, &tcam_ptr);
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_TCP_IPV6);
+ rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV6,
+ flow_cookie);
+ offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV6,
+ channel_cookie);
+
+ break;
+
+ case FSPEC_UDPIP6:
+
+ nxge_fill_tcam_entry_udp_ipv6(nxgep,
+ flow_spec, &tcam_ptr);
+
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_UDP_IPV6);
+ rdc_grp = nxge_get_rdc_group(nxgep,
+ TCAM_CLASS_UDP_IPV6,
+ channel_cookie);
+ offset = nxge_get_rdc_offset(nxgep,
+ TCAM_CLASS_UDP_IPV6,
+ flow_cookie);
+
+ break;
+
+ case FSPEC_SCTPIP4:
+
+ nxge_fill_tcam_entry_sctp(nxgep, flow_spec, &tcam_ptr);
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_SCTP_IPV4);
+ rdc_grp = nxge_get_rdc_group(nxgep,
+ TCAM_CLASS_SCTP_IPV4,
+ channel_cookie);
+ offset = nxge_get_rdc_offset(nxgep,
+ TCAM_CLASS_SCTP_IPV4,
+ flow_cookie);
+
+ break;
+
+ case FSPEC_SCTPIP6:
+
+ nxge_fill_tcam_entry_sctp_ipv6(nxgep,
+ flow_spec, &tcam_ptr);
+ location = nxge_get_tcam_location(nxgep,
+ TCAM_CLASS_SCTP_IPV4);
+ rdc_grp = nxge_get_rdc_group(nxgep,
+ TCAM_CLASS_SCTP_IPV6,
+ channel_cookie);
+ offset = nxge_get_rdc_offset(nxgep,
+ TCAM_CLASS_SCTP_IPV6,
+ flow_cookie);
+
+ break;
+
+
+ default:
+ return (NXGE_OK);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " nxge_add_tcam_entry write"
+ " for location %d offset %d", location, offset));
+
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_add_tcam_entry:"
+ " common hardware not set",
+ nxgep->niu_type));
+ return (NXGE_ERROR);
+ }
+ MUTEX_ENTER(&hw_p->nxge_tcam_lock);
+ rs = npi_fflp_tcam_entry_write(handle,
+ location, &tcam_ptr);
+
+ if (rs & NPI_FFLP_ERROR) {
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_add_tcam_entry write"
+ " failed for location %d",
+ location));
+ return (NXGE_ERROR | rs);
+ }
+ tcam_ptr.match_action.value = 0;
+ tcam_ptr.match_action.bits.ldw.rdctbl = rdc_grp;
+ tcam_ptr.match_action.bits.ldw.offset = offset;
+ tcam_ptr.match_action.bits.ldw.tres =
+ TRES_TERM_OVRD_L2RDC;
+ if (channel_cookie == -1)
+ tcam_ptr.match_action.bits.ldw.disc = 1;
+
+ rs = npi_fflp_tcam_asc_ram_entry_write(handle,
+ location,
+ tcam_ptr.match_action.value);
+
+ if (rs & NPI_FFLP_ERROR) {
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_add_tcam_entry write"
+ " failed for ASC RAM location %d",
+ location));
+ return (NXGE_ERROR | rs);
+ }
+
+ bcopy((void *)&tcam_ptr,
+ (void *)&nxgep->classifier.tcam_entries[location].tce,
+ sizeof (tcam_entry_t));
+
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_tcam_entry"));
+ return (NXGE_OK);
+}
+
+
+void
+nxge_handle_tcam_fragment_bug(p_nxge_t nxgep)
+{
+ tcam_entry_t tcam_ptr;
+ tcam_location_t location;
+ uint8_t class;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_hw_list_t hw_p;
+
+ handle = nxgep->npi_reg_handle;
+ class = 0;
+ bzero((void*)&tcam_ptr, sizeof (tcam_entry_t));
+ tcam_ptr.ip4_noport_key = 1;
+ tcam_ptr.ip4_noport_mask = 1;
+ location = nxge_get_tcam_location(nxgep, class);
+ nxgep->classifier.fragment_bug_location = location;
+
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_handle_tcam_fragment_bug:"
+ " common hardware not set",
+ nxgep->niu_type));
+ return;
+ }
+
+ MUTEX_ENTER(&hw_p->nxge_tcam_lock);
+ rs = npi_fflp_tcam_entry_write(handle,
+ location, &tcam_ptr);
+
+ if (rs & NPI_FFLP_ERROR) {
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_handle_tcam_fragment_bug "
+ " tcam_entry write"
+ " failed for location %d",
+ location));
+ return;
+ }
+
+ tcam_ptr.match_action.bits.ldw.rdctbl = nxgep->class_config.mac_rdcgrp;
+ tcam_ptr.match_action.bits.ldw.offset = 0; /* use the default */
+ tcam_ptr.match_action.bits.ldw.tres =
+ TRES_TERM_USE_OFFSET;
+
+ rs = npi_fflp_tcam_asc_ram_entry_write(handle,
+ location,
+ tcam_ptr.match_action.value);
+
+ if (rs & NPI_FFLP_ERROR) {
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+ NXGE_DEBUG_MSG((nxgep,
+ FFLP_CTL,
+ " nxge_handle_tcam_fragment_bug "
+ " tcam_entry write"
+ " failed for ASC RAM location %d",
+ location));
+ return;
+ }
+
+ bcopy((void *)&tcam_ptr,
+ (void *)&nxgep->classifier.tcam_entries[location].tce,
+ sizeof (tcam_entry_t));
+ MUTEX_EXIT(&hw_p->nxge_tcam_lock);
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+static int
+nxge_flow_need_hash_lookup(p_nxge_t nxgep,
+ flow_resource_t *flow_res)
+{
+ return (0);
+
+}
+
+
+nxge_status_t
+nxge_add_flow(p_nxge_t nxgep, flow_resource_t *flow_res)
+{
+
+ int insert_hash = 0;
+ nxge_status_t status = NXGE_OK;
+
+ if (nxgep->niu_type == NEPTUNE) {
+ /* determine whether to do TCAM or Hash flow */
+ insert_hash = nxge_flow_need_hash_lookup(nxgep, flow_res);
+ }
+
+ if (insert_hash) {
+ status = nxge_add_fcram_entry(nxgep, flow_res);
+ } else {
+ status = nxge_add_tcam_entry(nxgep, flow_res);
+ }
+
+ return (status);
+}
+
+#ifdef lint
+/* ARGSUSED */
+#endif
+void
+nxge_put_tcam(p_nxge_t nxgep, p_mblk_t mp)
+{
+
+ flow_resource_t *fs;
+ fs = (flow_resource_t *)mp->b_rptr;
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_put_tcam addr fs $%p type %x offset %x",
+ fs, fs->flow_spec.flow_type, fs->channel_cookie));
+
+ (void) nxge_add_tcam_entry(nxgep, fs);
+}
+
+
+nxge_status_t
+nxge_fflp_config_tcam_enable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_config_tcam_enable"));
+ rs = npi_fflp_cfg_tcam_enable(handle);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_tcam_enable failed"));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_config_tcam_enable"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_config_tcam_disable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_fflp_config_tcam_disable"));
+ rs = npi_fflp_cfg_tcam_disable(handle);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_tcam_disable failed"));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_fflp_config_tcam_disable"));
+ return (NXGE_OK);
+}
+
+
+
+nxge_status_t
+nxge_fflp_config_hash_lookup_enable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint8_t partition;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_fflp_config_hash_lookup_enable"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+
+ for (partition = p_cfgp->start_rdc_grpid;
+ partition < p_cfgp->max_rdc_grpids; partition++) {
+ rs = npi_fflp_cfg_fcram_partition_enable(handle,
+ partition);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_hash_lookup_enable"
+ "failed FCRAM partition"
+ " enable for partition %d ",
+ partition));
+ return (NXGE_ERROR | rs);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_fflp_config_hash_lookup_enable"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_config_hash_lookup_disable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint8_t partition;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_fflp_config_hash_lookup_disable"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+
+ for (partition = p_cfgp->start_rdc_grpid;
+ partition < p_cfgp->max_rdc_grpids; partition++) {
+ rs = npi_fflp_cfg_fcram_partition_disable(handle,
+ partition);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_hash_lookup_disable"
+ " failed FCRAM partition"
+ " disable for partition %d ",
+ partition));
+ return (NXGE_ERROR | rs);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_fflp_config_hash_lookup_disable"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_fflp_config_llc_snap_enable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_fflp_config_llc_snap_enable"));
+ rs = npi_fflp_cfg_llcsnap_enable(handle);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_llc_snap_enable failed"));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_fflp_config_llc_snap_enable"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_config_llc_snap_disable(p_nxge_t nxgep)
+{
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ npi_status_t rs = NPI_SUCCESS;
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " ==> nxge_fflp_config_llc_snap_disable"));
+ rs = npi_fflp_cfg_llcsnap_disable(handle);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_llc_snap_disable failed"));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " <== nxge_fflp_config_llc_snap_disable"));
+ return (NXGE_OK);
+}
+
+
+
+nxge_status_t
+nxge_fflp_ip_usr_class_config(p_nxge_t nxgep, tcam_class_t class,
+ uint32_t config)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle = nxgep->npi_reg_handle;
+ uint8_t tos, tos_mask, proto, ver = 0;
+ uint8_t class_enable = 0;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_usr_class_config"));
+
+ tos = (config & NXGE_CLASS_CFG_IP_TOS_MASK) >>
+ NXGE_CLASS_CFG_IP_TOS_SHIFT;
+ tos_mask = (config & NXGE_CLASS_CFG_IP_TOS_MASK_MASK) >>
+ NXGE_CLASS_CFG_IP_TOS_MASK_SHIFT;
+ proto = (config & NXGE_CLASS_CFG_IP_PROTO_MASK) >>
+ NXGE_CLASS_CFG_IP_PROTO_SHIFT;
+
+ if (config & NXGE_CLASS_CFG_IP_IPV6_MASK)
+ ver = 1;
+ if (config & NXGE_CLASS_CFG_IP_ENABLE_MASK)
+ class_enable = 1;
+
+ rs = npi_fflp_cfg_ip_usr_cls_set(handle, class, tos, tos_mask,
+ proto, ver);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_ip_usr_class_config"
+ " for class %d failed ", class));
+ return (NXGE_ERROR | rs);
+ }
+
+ if (class_enable)
+ rs = npi_fflp_cfg_ip_usr_cls_enable(handle, class);
+ else
+ rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
+
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_ip_usr_class_config"
+ " TCAM enable/disable for class %d failed ",
+ class));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_usr_class_config"));
+ return (NXGE_OK);
+}
+
+
+
+nxge_status_t
+nxge_fflp_ip_class_config(p_nxge_t nxgep, tcam_class_t class,
+ uint32_t config)
+{
+
+ uint32_t class_config;
+ nxge_status_t t_status = NXGE_OK;
+ nxge_status_t f_status = NXGE_OK;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ class_config = p_class_cfgp->class_cfg[class];
+
+ if (class_config != config) {
+ p_class_cfgp->class_cfg[class] = config;
+ class_config = config;
+ }
+
+ t_status = nxge_cfg_tcam_ip_class(nxgep, class, class_config);
+ f_status = nxge_cfg_ip_cls_flow_key(nxgep, class, class_config);
+
+ if (t_status & NPI_FFLP_ERROR) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " nxge_fflp_ip_class_config %x"
+ " for class %d tcam failed", config,
+ class));
+ return (t_status);
+ }
+
+ if (f_status & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_ip_class_config %x"
+ " for class %d flow key failed", config,
+ class));
+ return (f_status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_fflp_ip_class_config_get(p_nxge_t nxgep, tcam_class_t class,
+ uint32_t *config)
+{
+
+ uint32_t t_class_config, f_class_config;
+ int t_status = NXGE_OK;
+ int f_status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
+ t_class_config = f_class_config = 0;
+ t_status = nxge_cfg_tcam_ip_class_get(nxgep, class, &t_class_config);
+ f_status = nxge_cfg_ip_cls_flow_key_get(nxgep, class, &f_class_config);
+
+
+ if (t_status & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_ip_class_config_get "
+ " for class %d tcam failed", class));
+ return (t_status);
+ }
+
+ if (f_status & NPI_FFLP_ERROR) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " nxge_fflp_ip_class_config_get "
+ " for class %d flow key failed", class));
+ return (f_status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ " nxge_fflp_ip_class_config tcam %x flow %x",
+ t_class_config, f_class_config));
+
+ *config = t_class_config | f_class_config;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config_get"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_fflp_ip_class_config_all(p_nxge_t nxgep)
+{
+
+ uint32_t class_config;
+ tcam_class_t class;
+
+#ifdef NXGE_DEBUG
+ int status = NXGE_OK;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_class_config"));
+ for (class = TCAM_CLASS_TCP_IPV4;
+ class <= TCAM_CLASS_SCTP_IPV6; class++) {
+ class_config = nxgep->class_config.class_cfg[class];
+#ifndef NXGE_DEBUG
+ (void) nxge_fflp_ip_class_config(nxgep, class, class_config);
+#else
+ status = nxge_fflp_ip_class_config(nxgep, class, class_config);
+ if (status & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_fflp_ip_class_config failed "
+ " class %d config %x ",
+ class, class_config));
+ }
+#endif
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
+ return (NXGE_OK);
+}
+
+
+
+nxge_status_t
+nxge_fflp_config_vlan_table(p_nxge_t nxgep, uint16_t vlan_id)
+{
+ uint8_t port, rdc_grp;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ uint8_t priority = 1;
+ p_nxge_mv_cfg_t vlan_table;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ p_nxge_hw_list_t hw_p;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_config_vlan_table"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ handle = nxgep->npi_reg_handle;
+ vlan_table = p_class_cfgp->vlan_tbl;
+ port = nxgep->function_num;
+
+ if (vlan_table[vlan_id].flag == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_vlan_table"
+ " vlan id is not configured %d", vlan_id));
+ return (NXGE_ERROR);
+ }
+
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_fflp_config_vlan_table:"
+ " common hardware not set",
+ nxgep->niu_type));
+ return (NXGE_ERROR);
+ }
+
+ MUTEX_ENTER(&hw_p->nxge_vlan_lock);
+ rdc_grp = vlan_table[vlan_id].rdctbl;
+ rs = npi_fflp_cfg_enet_vlan_table_assoc(handle,
+ port, vlan_id,
+ rdc_grp, priority);
+
+ MUTEX_EXIT(&hw_p->nxge_vlan_lock);
+ if (rs & NPI_FFLP_ERROR) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_fflp_config_vlan_table failed "
+ " Port %d vlan_id %d rdc_grp %d",
+ port, vlan_id, rdc_grp));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_config_vlan_table"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fflp_update_hw(p_nxge_t nxgep)
+{
+
+ nxge_status_t status = NXGE_OK;
+ p_nxge_param_t pa;
+ uint64_t cfgd_vlans;
+ uint64_t *val_ptr;
+ int i;
+ int num_macs;
+ uint8_t alt_mac;
+ nxge_param_map_t *p_map;
+
+ p_nxge_mv_cfg_t vlan_table;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ p_nxge_dma_pt_cfg_t p_all_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_update_hw"));
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
+
+ status = nxge_fflp_set_hash1(nxgep, p_class_cfgp->init_h1);
+ if (status != NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_fflp_set_hash1 Failed"));
+ return (NXGE_ERROR);
+ }
+
+ status = nxge_fflp_set_hash2(nxgep, p_class_cfgp->init_h2);
+ if (status != NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_fflp_set_hash2 Failed"));
+ return (NXGE_ERROR);
+ }
+
+ vlan_table = p_class_cfgp->vlan_tbl;
+
+/* configure vlan tables */
+ pa = (p_nxge_param_t)&nxgep->param_arr[param_vlan_2rdc_grp];
+ val_ptr = (uint64_t *)pa->value;
+ cfgd_vlans = ((pa->type & NXGE_PARAM_ARRAY_CNT_MASK) >>
+ NXGE_PARAM_ARRAY_CNT_SHIFT);
+
+ for (i = 0; i < cfgd_vlans; i++) {
+ p_map = (nxge_param_map_t *)&val_ptr[i];
+ if (vlan_table[p_map->param_id].flag) {
+ status = nxge_fflp_config_vlan_table(nxgep,
+ p_map->param_id);
+ if (status != NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_fflp_config_vlan_table Failed"));
+ return (NXGE_ERROR);
+ }
+ }
+ }
+ /* config MAC addresses */
+ num_macs = p_cfgp->max_macs;
+ pa = (p_nxge_param_t)&nxgep->param_arr[param_mac_2rdc_grp];
+ val_ptr = (uint64_t *)pa->value;
+
+ for (alt_mac = 0; alt_mac < num_macs; alt_mac++) {
+ if (p_class_cfgp->mac_host_info[alt_mac].flag) {
+ status = nxge_logical_mac_assign_rdc_table(nxgep,
+ alt_mac);
+ if (status != NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_logical_mac_assign_rdc_table Failed"));
+ return (NXGE_ERROR);
+ }
+ }
+ }
+ /* Config Hash values */
+ /* config classess */
+ status = nxge_fflp_ip_class_config_all(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_fflp_ip_class_config_all Failed"));
+ return (NXGE_ERROR);
+ }
+
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_classify_init_hw(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_hw"));
+
+ if (nxgep->classifier.state & NXGE_FFLP_HW_INIT) {
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
+ "nxge_classify_init_hw already init"));
+ return (NXGE_OK);
+ }
+
+
+/* Now do a real configuration */
+ status = nxge_fflp_update_hw(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_fflp_update_hw failed"));
+ return (NXGE_ERROR);
+ }
+/* Init RDC tables? ? who should do that? rxdma or fflp ? */
+/* attach rdc table to the MAC port. */
+ status = nxge_main_mac_assign_rdc_table(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_main_mac_assign_rdc_table failed"));
+ return (NXGE_ERROR);
+ }
+ status = nxge_multicast_mac_assign_rdc_table(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_multicast_mac_assign_rdc_table failed"));
+ return (NXGE_ERROR);
+ }
+/* If requested, attach RDC table to VLAN ID */
+
+ nxgep->classifier.state |= NXGE_FFLP_HW_INIT;
+
+ NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_hw"));
+
+ return (NXGE_OK);
+
+}
+
+nxge_status_t
+nxge_fflp_handle_sys_errors(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ p_nxge_fflp_stats_t statsp;
+ uint8_t portn, rdc_grp;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ vlan_par_err_t vlan_err;
+ tcam_err_t tcam_err;
+ hash_lookup_err_log1_t fcram1_err;
+ hash_lookup_err_log2_t fcram2_err;
+ hash_tbl_data_log_t fcram_err;
+
+ handle = nxgep->npi_handle;
+ statsp = (p_nxge_fflp_stats_t)&nxgep->statsp->fflp_stats;
+ portn = nxgep->mac.portnum;
+
+ /*
+ * need to read the fflp error registers to figure out
+ * what the error is
+ */
+ npi_fflp_vlan_error_get(handle, &vlan_err);
+ npi_fflp_tcam_error_get(handle, &tcam_err);
+
+ if (vlan_err.bits.ldw.m_err || vlan_err.bits.ldw.err) {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " vlan table parity error on port %d"
+ " addr: 0x%x data: 0x%x",
+ portn, vlan_err.bits.ldw.addr,
+ vlan_err.bits.ldw.data));
+ statsp->vlan_parity_err++;
+
+ if (vlan_err.bits.ldw.m_err) {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " vlan table multiple errors on port %d",
+ portn));
+ }
+
+ statsp->errlog.vlan = (uint32_t)vlan_err.value;
+ NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
+ NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR);
+ npi_fflp_vlan_error_clear(handle);
+ }
+
+ if (tcam_err.bits.ldw.err) {
+ if (tcam_err.bits.ldw.p_ecc != 0) {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " TCAM ECC error on port %d"
+ " TCAM entry: 0x%x syndrome: 0x%x",
+ portn, tcam_err.bits.ldw.addr,
+ tcam_err.bits.ldw.syndrome));
+ statsp->tcam_ecc_err++;
+ } else {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " TCAM Parity error on port %d"
+ " addr: 0x%x parity value: 0x%x",
+ portn, tcam_err.bits.ldw.addr,
+ tcam_err.bits.ldw.syndrome));
+ statsp->tcam_parity_err++;
+ }
+
+ if (tcam_err.bits.ldw.mult) {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " TCAM Multiple errors on port %d",
+ portn));
+ } else {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " TCAM PIO error on port %d",
+ portn));
+ }
+
+ statsp->errlog.tcam = (uint32_t)tcam_err.value;
+ NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
+ NXGE_FM_EREPORT_FFLP_TCAM_ERR);
+ npi_fflp_tcam_error_clear(handle);
+ }
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ for (rdc_grp = p_cfgp->start_rdc_grpid;
+ rdc_grp < p_cfgp->max_rdc_grpids; rdc_grp++) {
+ npi_fflp_fcram_error_get(handle, &fcram_err, rdc_grp);
+ if (fcram_err.bits.ldw.pio_err) {
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " FCRAM PIO ECC error on port %d"
+ " rdc group: %d Hash Table addr: 0x%x"
+ " syndrome: 0x%x",
+ portn, rdc_grp,
+ fcram_err.bits.ldw.fcram_addr,
+ fcram_err.bits.ldw.syndrome));
+ statsp->hash_pio_err[rdc_grp]++;
+ statsp->errlog.hash_pio[rdc_grp] =
+ (uint32_t)fcram_err.value;
+ NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
+ NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR);
+ npi_fflp_fcram_error_clear(handle, rdc_grp);
+ }
+ }
+
+ npi_fflp_fcram_error_log1_get(handle, &fcram1_err);
+ if (fcram1_err.bits.ldw.ecc_err) {
+ char *multi_str = "";
+ char *multi_bit_str = "";
+ npi_fflp_fcram_error_log2_get(handle, &fcram2_err);
+ if (fcram1_err.bits.ldw.mult_lk) {
+ multi_str = "multiple";
+ }
+ if (fcram1_err.bits.ldw.mult_bit) {
+ multi_bit_str = "multiple bits";
+ }
+ NXGE_ERROR_MSG((nxgep, FFLP_CTL,
+ " FCRAM %s lookup %s ECC error on port %d"
+ " H1: 0x%x Subarea: 0x%x Syndrome: 0x%x",
+ multi_str, multi_bit_str, portn,
+ fcram2_err.bits.ldw.h1,
+ fcram2_err.bits.ldw.subarea,
+ fcram2_err.bits.ldw.syndrome));
+ NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
+ NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR);
+ }
+ statsp->errlog.hash_lookup1 = (uint32_t)fcram1_err.value;
+ statsp->errlog.hash_lookup2 = (uint32_t)fcram2_err.value;
+
+ return (NXGE_OK);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_fflp_hash.c b/usr/src/uts/sun4v/io/nxge/nxge_fflp_hash.c
new file mode 100644
index 0000000000..5d4ca61fd2
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_fflp_hash.c
@@ -0,0 +1,404 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef LINUX
+#include <stdint.h>
+#endif
+
+#include <nxge_fflp_hash.h>
+
+static void nxge_crc32c_word(uint32_t *crcptr, const uint32_t *buf, int len);
+/*
+ * The crc32c algorithms are taken from sctp_crc32 implementation
+ * common/inet/sctp_crc32.{c,h}
+ *
+ */
+
+/*
+ * Fast CRC32C calculation algorithm suggested by Ferenc Rakoczi
+ * (ferenc.rakoczi@sun.com). The basic idea is to look at it
+ * four bytes (one word) at a time, using four tables. The
+ * standard algorithm in RFC 3309 uses one table.
+ */
+
+/*
+ * SCTP uses reflected/reverse polynomial CRC32 with generating
+ * polynomial 0x1EDC6F41L
+ */
+#define SCTP_POLY 0x1EDC6F41L
+
+/* CRC-CCITT Polynomial */
+#define CRC_CCITT_POLY 0x1021
+
+/* The four CRC32c tables. */
+static uint32_t crc32c_tab[4][256];
+
+/* The four CRC-CCITT tables. */
+static uint16_t crc_ccitt_tab[4][256];
+
+/* the four tables for H1 Computation */
+static uint32_t h1table[4][256];
+
+#define CRC_32C_POLY 0x1EDC6F41L
+
+#define COMPUTE_H1_BYTE(crc, data) \
+ (crc = (crc<<8)^h1table[0][((crc >> 24) ^data) & 0xff])
+
+
+static uint32_t
+reflect_32(uint32_t b)
+{
+ int i;
+ uint32_t rw = 0;
+
+ for (i = 0; i < 32; i++) {
+ if (b & 1) {
+ rw |= 1 << (31 - i);
+ }
+ b >>= 1;
+ }
+ return (rw);
+}
+
+static uint32_t
+flip32(uint32_t w)
+{
+ return (((w >> 24) | ((w >> 8) & 0xff00) | ((w << 8) & 0xff0000) |
+ (w << 24)));
+}
+
+/*
+ * reference crc-ccitt implementation
+ */
+
+uint16_t
+crc_ccitt(uint16_t crcin, uint8_t data)
+{
+ uint16_t mcrc, crc = 0, bits = 0;
+
+ mcrc = (((crcin >> 8) ^ data) & 0xff) << 8;
+ for (bits = 0; bits < 8; bits++) {
+ crc = ((crc ^ mcrc) & 0x8000) ?
+ (crc << 1) ^ CRC_CCITT_POLY :
+ crc << 1;
+ mcrc <<= 1;
+ }
+ return ((crcin << 8) ^ crc);
+}
+
+
+
+/*
+ * Initialize the crc32c tables.
+ */
+
+void
+nxge_crc32c_init(void)
+{
+ uint32_t index, bit, byte, crc;
+
+ for (index = 0; index < 256; index++) {
+ crc = reflect_32(index);
+ for (byte = 0; byte < 4; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ crc = (crc & 0x80000000) ?
+ (crc << 1) ^ SCTP_POLY : crc << 1;
+ }
+#ifdef _BIG_ENDIAN
+ crc32c_tab[3 - byte][index] = flip32(reflect_32(crc));
+#else
+ crc32c_tab[byte][index] = reflect_32(crc);
+#endif
+ }
+ }
+}
+
+
+/*
+ * Initialize the crc-ccitt tables.
+ */
+
+void
+nxge_crc_ccitt_init(void)
+{
+
+ uint16_t crc;
+ uint16_t index, bit, byte;
+
+ for (index = 0; index < 256; index++) {
+ crc = index << 8;
+ for (byte = 0; byte < 4; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ crc = (crc & 0x8000) ?
+ (crc << 1) ^ CRC_CCITT_POLY : crc << 1;
+ }
+
+#ifdef _BIG_ENDIAN
+ crc_ccitt_tab[3 - byte][index] = crc;
+#else
+ crc_ccitt_tab[byte][index] = crc;
+#endif
+ }
+ }
+
+}
+
+
+/*
+ * Lookup the crc32c for a byte stream
+ */
+
+static void
+nxge_crc32c_byte(uint32_t *crcptr, const uint8_t *buf, int len)
+{
+ uint32_t crc;
+ int i;
+
+ crc = *crcptr;
+ for (i = 0; i < len; i++) {
+#ifdef _BIG_ENDIAN
+ crc = (crc << 8) ^ crc32c_tab[3][buf[i] ^ (crc >> 24)];
+#else
+ crc = (crc >> 8) ^ crc32c_tab[0][buf[i] ^ (crc & 0xff)];
+#endif
+ }
+ *crcptr = crc;
+}
+
+
+
+/*
+ * Lookup the crc-ccitt for a byte stream
+ */
+
+static void
+nxge_crc_ccitt_byte(uint16_t *crcptr, const uint8_t *buf, int len)
+{
+ uint16_t crc;
+ int i;
+
+ crc = *crcptr;
+ for (i = 0; i < len; i++) {
+
+#ifdef _BIG_ENDIAN
+ crc = (crc << 8) ^ crc_ccitt_tab[3][buf[i] ^ (crc >> 8)];
+#else
+ crc = (crc << 8) ^ crc_ccitt_tab[0][buf[i] ^ (crc >> 8)];
+#endif
+ }
+ *crcptr = crc;
+}
+
+
+
+
+/*
+ * Lookup the crc32c for a 32 bit word stream
+ * Lookup is done fro the 4 bytes in parallel
+ * from the tables computed earlier
+ *
+ */
+
+static void
+nxge_crc32c_word(uint32_t *crcptr, const uint32_t *buf, int len)
+{
+ uint32_t w, crc;
+ int i;
+
+ crc = *crcptr;
+ for (i = 0; i < len; i++) {
+ w = crc ^ buf[i];
+ crc = crc32c_tab[0][w >> 24] ^ crc32c_tab[1][(w >> 16) & 0xff] ^
+ crc32c_tab[2][(w >> 8) & 0xff] ^ crc32c_tab[3][w & 0xff];
+ }
+ *crcptr = crc;
+}
+
+/*
+ * Lookup the crc-ccitt for a stream of bytes
+ *
+ * Since the parallel lookup version doesn't work yet,
+ * use the byte stream version (lookup crc for a byte
+ * at a time
+ *
+ */
+uint16_t
+nxge_crc_ccitt(uint16_t crc16, const uint8_t *buf, int len)
+{
+
+ nxge_crc_ccitt_byte(&crc16, buf, len);
+
+ return (crc16);
+}
+
+
+
+/*
+ * Lookup the crc32c for a stream of bytes
+ *
+ * Tries to lookup the CRC on 4 byte words
+ * If the buffer is not 4 byte aligned, first compute
+ * with byte lookup until aligned. Then compute crc
+ * for each 4 bytes. If there are bytes left at the end of
+ * the buffer, then perform a byte lookup for the remaining bytes
+ *
+ *
+ */
+
+uint32_t
+nxge_crc32c(uint32_t crc32, const uint8_t *buf, int len)
+{
+ int rem;
+
+ rem = 4 - ((uintptr_t)buf) & 3;
+ if (rem != 0) {
+ if (len < rem) {
+ rem = len;
+ }
+ nxge_crc32c_byte(&crc32, buf, rem);
+ buf = buf + rem;
+ len = len - rem;
+ }
+
+ if (len > 3) {
+ nxge_crc32c_word(&crc32, (const uint32_t *)buf, len / 4);
+ }
+
+ rem = len & 3;
+ if (rem != 0) {
+ nxge_crc32c_byte(&crc32, buf + len - rem, rem);
+ }
+ return (crc32);
+}
+
+
+
+
+void
+nxge_init_h1_table()
+{
+ uint32_t crc, bit, byte, index;
+
+ for (index = 0; index < 256; index ++) {
+ crc = index << 24;
+ for (byte = 0; byte < 4; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ crc = ((crc & 0x80000000)) ?
+ (crc << 1) ^ CRC_32C_POLY : crc << 1;
+ }
+ h1table[byte][index] = crc;
+ }
+ }
+}
+
+
+/*
+ * Reference Neptune H1 computation function
+ *
+ * It is a slightly modified implementation of
+ * CRC-32C implementation
+ */
+
+uint32_t
+nxge_compute_h1_serial(uint32_t init_value,
+ uint32_t *flow, uint32_t len)
+{
+ int bit, byte;
+ uint32_t crc_h1 = init_value;
+ uint8_t *buf;
+ buf = (uint8_t *)flow;
+ for (byte = 0; byte < len; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ crc_h1 = (((crc_h1 >> 24) & 0x80) ^
+ ((buf[byte] << bit) & 0x80)) ?
+ (crc_h1 << 1) ^ CRC_32C_POLY : crc_h1 << 1;
+ }
+ }
+
+ return (crc_h1);
+}
+
+
+
+/*
+ * table based implementation
+ * uses 4 four tables in parallel
+ * 1 for each byte of a 32 bit word
+ *
+ * This is the default h1 computing function
+ *
+ */
+
+uint32_t
+nxge_compute_h1_table4(uint32_t crcin,
+ uint32_t *flow, uint32_t length)
+{
+
+ uint32_t w, fw, i, crch1 = crcin;
+ uint32_t *buf;
+ buf = (uint32_t *)flow;
+
+ for (i = 0; i < length / 4; i++) {
+#ifdef _BIG_ENDIAN
+ fw = buf[i];
+#else
+ fw = flip32(buf[i]);
+ fw = buf[i];
+#endif
+ w = crch1 ^ fw;
+ crch1 = h1table[3][w >> 24] ^ h1table[2][(w >> 16) & 0xff] ^
+ h1table[1][(w >> 8) & 0xff] ^ h1table[0][w & 0xff];
+ }
+ return (crch1);
+}
+
+
+
+/*
+ * table based implementation
+ * uses a single table and computes h1 for a byte
+ * at a time.
+ *
+ */
+
+uint32_t
+nxge_compute_h1_table1(uint32_t crcin, uint32_t *flow, uint32_t length)
+{
+
+ uint32_t i, crch1, tmp = crcin;
+ uint8_t *buf;
+ buf = (uint8_t *)flow;
+
+ tmp = crcin;
+ for (i = 0; i < length; i++) {
+ crch1 = COMPUTE_H1_BYTE(tmp, buf[i]);
+ tmp = crch1;
+ }
+
+ return (crch1);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_fm.c b/usr/src/uts/sun4v/io/nxge/nxge_fm.c
new file mode 100644
index 0000000000..b740544998
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_fm.c
@@ -0,0 +1,856 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/ddifm.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
+#include <sys/fm/io/ddi.h>
+
+static nxge_fm_ereport_attr_t
+*nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t);
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_pcs[] = {
+ {NXGE_FM_EREPORT_XPCS_LINK_DOWN, "10g.link_down",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT, "10g.tx_link_fault",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT, "10g.rx_link_fault",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_PCS_LINK_DOWN, "1g.link_down",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_PCS_REMOTE_FAULT, "1g.remote_fault",
+ DDI_SERVICE_DEGRADED},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_mif[] = {
+ {NXGE_FM_EREPORT_MIF_ACCESS_FAIL, "transceiver.access_fail"}
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_fflp[] = {
+ {NXGE_FM_EREPORT_FFLP_TCAM_ERR, "classifier.tcam_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR, "classifier.vlan_par_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR, "classifier.hasht_data_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR, "classifier.hasht_lookup_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_FFLP_ACCESS_FAIL, "classifier.access_fail",
+ DDI_SERVICE_DEGRADED}
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_ipp[] = {
+ {NXGE_FM_EREPORT_IPP_EOP_MISS, "rx.eop_miss",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_SOP_MISS, "rx.sop_miss",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_DFIFO_UE, "rx.dfifo_ucorr_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_DFIFO_CE, "rx.dfifo_corr_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_IPP_PFIFO_PERR, "rx.dfifo_parity_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_ECC_ERR_MAX, "rx.ecc_err_max",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_IPP_PFIFO_OVER, "rx.pfifo_overflow",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_PFIFO_UND, "rx.pfifo_underrun",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_IPP_BAD_CS_MX, "rx.bad_cksum_max",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_IPP_PKT_DIS_MX, "rx.pkt_discard_max",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_IPP_RESET_FAIL, "rx.reset_fail",
+ DDI_SERVICE_LOST}
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_rdmc[] = {
+ {NXGE_FM_EREPORT_RDMC_DCF_ERR, "rxdma.dcf_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR, "rxdma.rcr_ack_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR, "rxdma.dc_fifo_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR, "rxdma.rcr_sha_par_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR, "rxdma.rbr_pre_par_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RBR_TMOUT, "rxdma.rbr_tmout",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR, "rxdma.rsp_cnt_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS, "rxdma.byte_en_bus",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR, "rxdma.rsp_dat_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_ID_MISMATCH, "rxdma.id_mismatch",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR, "rxdma.zcp_eop_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR, "rxdma.ipp_eop_err",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_RDMC_COMPLETION_ERR, "rxdma.completion_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RDMC_CONFIG_ERR, "rxdma.config_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RCRINCON, "rxdma.rcrincon",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RCRFULL, "rxdma.rcrfull",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RBRFULL, "rxdma.rbrfull",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_RBRLOGPAGE, "rxdma.rbrlogpage",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE, "rxdma.cfiglogpage",
+ DDI_SERVICE_DEGRADED}
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_zcp[] = {
+ {NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN, "rxzcopy.rrfifo_underrun",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR,
+ "rxzcopy.rspfifo_uncorr_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR, "rxzcopy.stat_tbl_perr",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR, "rxzcopy.dyn_tbl_perr",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR, "rxzcopy.buf_tbl_perr",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_CFIFO_ECC, "rxzcopy.cfifo_ecc",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN, "rxzcopy.rrfifo_overrun",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW, "rxzcopy.buffer_overflow",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR, "rxzcopy.tt_program_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR, "rxzcopy.rsp_tt_index_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR, "rxzcopy.slv_tt_index_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR, "rxzcopy.tt_index_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_ZCP_ACCESS_FAIL, "rxzcopy.access_fail",
+ DDI_SERVICE_LOST},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_rxmac[] = {
+ {NXGE_FM_EREPORT_RXMAC_UNDERFLOW, "rxmac.underflow",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP, "rxmac.crc_errcnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP,
+ "rxmac.length_errcnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP, "rxmac.viol_errcnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP, "rxmac.rxfrag_cnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP, "rxmac.align_ecnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP,
+ "rxmac.linkfault_cnt_exp",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_RXMAC_RESET_FAIL, "rxmac.reset_fail",
+ DDI_SERVICE_UNAFFECTED},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_tdmc[] = {
+ {NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR, "txdma.pref_buf_par_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_MBOX_ERR, "txdma.mbox_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_NACK_PREF, "txdma.nack_pref",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_NACK_PKT_RD, "txdma.nack_pkt_rd",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR, "txdma.pkt_size_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW, "txdma.tx_ring_oflow",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_CONF_PART_ERR, "txdma.conf_part_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR, "txdma.pkt_prt_err",
+ DDI_SERVICE_DEGRADED},
+ {NXGE_FM_EREPORT_TDMC_RESET_FAIL, "txdma.reset_fail"}
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_txc[] = {
+ {NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR, "tx.ro_correct_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR, "tx.ro_uncorrect_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR, "tx.sf_correct_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR, "tx.sf_uncorrect_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXC_ASSY_DEAD, "tx.assembly_uncorrect_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXC_REORDER_ERR, "tx.reorder_err",
+ DDI_SERVICE_LOST},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_txmac[] = {
+ {NXGE_FM_EREPORT_TXMAC_UNDERFLOW, "txmac.underflow",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXMAC_OVERFLOW, "txmac.overflow",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR, "txmac.txfifo_xfr_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR, "txmac.max_pkt_err",
+ DDI_SERVICE_UNAFFECTED},
+ {NXGE_FM_EREPORT_TXMAC_RESET_FAIL, "txmac.reset_fail",
+ DDI_SERVICE_UNAFFECTED},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_espc[] = {
+ {NXGE_FM_EREPORT_ESPC_ACCESS_FAIL, "eprom.access_fail",
+ DDI_SERVICE_LOST},
+};
+
+nxge_fm_ereport_attr_t nxge_fm_ereport_sw[] = {
+ {NXGE_FM_EREPORT_SW_INVALID_PORT_NUM, "invalid_port_num",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM, "invalid_chan_num",
+ DDI_SERVICE_LOST},
+ {NXGE_FM_EREPORT_SW_INVALID_PARAM, "invalid_param",
+ DDI_SERVICE_LOST},
+};
+
+void
+nxge_fm_init(p_nxge_t nxgep, ddi_device_acc_attr_t *reg_attr,
+ ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr)
+{
+ ddi_iblock_cookie_t iblk;
+
+ nxgep->fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, nxgep->dip,
+ DDI_PROP_DONTPASS, "fm-capable", 0);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "FM capable = %d\n", nxgep->fm_capabilities));
+
+ /* Only register with IO Fault Services if we have some capability */
+ if (nxgep->fm_capabilities) {
+ reg_attr->devacc_attr_access = DDI_FLAGERR_ACC;
+ desc_attr->devacc_attr_access = DDI_FLAGERR_ACC;
+ dma_attr->dma_attr_flags = DDI_DMA_FLAGERR;
+
+ /* Register capabilities with IO Fault Services */
+ ddi_fm_init(nxgep->dip, &nxgep->fm_capabilities, &iblk);
+
+ /*
+ * Initialize pci ereport capabilities if ereport capable
+ */
+ if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
+ DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
+ pci_ereport_setup(nxgep->dip);
+ } else {
+ /*
+ * These fields have to be cleared of FMA if there are no
+ * FMA capabilities at runtime.
+ */
+ reg_attr->devacc_attr_access = DDI_DEFAULT_ACC;
+ desc_attr->devacc_attr_access = DDI_DEFAULT_ACC;
+ dma_attr->dma_attr_flags = 0;
+ }
+}
+
+void
+nxge_fm_fini(p_nxge_t nxgep)
+{
+ /* Only unregister FMA capabilities if we registered some */
+ if (nxgep->fm_capabilities) {
+
+ /*
+ * Release any resources allocated by pci_ereport_setup()
+ */
+ if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
+ DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
+ pci_ereport_teardown(nxgep->dip);
+
+ /*
+ * Un-register error callback if error callback capable
+ */
+ if (DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
+ ddi_fm_handler_unregister(nxgep->dip);
+
+ /* Unregister from IO Fault Services */
+ ddi_fm_fini(nxgep->dip);
+ }
+}
+
+void
+nxge_fm_npi_error_handler(p_nxge_t nxgep, npi_status_t status)
+{
+ uint8_t block_id;
+ uint8_t error_type;
+ nxge_fm_ereport_id_t fm_ereport_id;
+ nxge_fm_ereport_attr_t *fm_ereport_attr;
+ char *class_name;
+ uint64_t ena;
+ uint8_t portn = 0;
+ uint8_t chan = 0;
+ boolean_t is_port;
+ boolean_t is_chan;
+
+ if (status == NPI_SUCCESS)
+ return;
+
+ block_id = (status >> NPI_BLOCK_ID_SHIFT) & 0xF;
+ error_type = status & 0xFF;
+ is_port = (status & IS_PORT)? B_TRUE: B_FALSE;
+ is_chan = (status & IS_CHAN)? B_TRUE: B_FALSE;
+
+ if (is_port)
+ portn = (status >> NPI_PORT_CHAN_SHIFT) & 0xF;
+ else if (is_chan)
+ chan = (status >> NPI_PORT_CHAN_SHIFT) & 0xF;
+
+ /* Map error type into FM ereport id */
+
+ /* Handle all software errors */
+
+ if (((error_type >= COMMON_SW_ERR_START) &&
+ (error_type <= COMMON_SW_ERR_END)) ||
+ ((error_type >= BLK_SPEC_SW_ERR_START) &&
+ (error_type <= BLK_SPEC_SW_ERR_END))) {
+ switch (error_type) {
+ case PORT_INVALID:
+ fm_ereport_id = NXGE_FM_EREPORT_SW_INVALID_PORT_NUM;
+ break;
+ case CHANNEL_INVALID:
+ fm_ereport_id = NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM;
+ break;
+ default:
+ fm_ereport_id = NXGE_FM_EREPORT_SW_INVALID_PARAM;
+ }
+ } else if (((error_type >= COMMON_HW_ERR_START) &&
+ (error_type <= COMMON_HW_ERR_END)) ||
+ ((error_type >= BLK_SPEC_HW_ERR_START) &&
+ (error_type <= BLK_SPEC_SW_ERR_END))) {
+ /* Handle hardware errors */
+ switch (error_type) {
+ case RESET_FAILED:
+ switch (block_id) {
+ case TXMAC_BLK_ID:
+ fm_ereport_id =
+ NXGE_FM_EREPORT_TXMAC_RESET_FAIL;
+ break;
+ case RXMAC_BLK_ID:
+ fm_ereport_id =
+ NXGE_FM_EREPORT_RXMAC_RESET_FAIL;
+ break;
+ case IPP_BLK_ID:
+ fm_ereport_id = NXGE_FM_EREPORT_IPP_RESET_FAIL;
+ break;
+ case TXDMA_BLK_ID:
+ fm_ereport_id = NXGE_FM_EREPORT_TDMC_RESET_FAIL;
+ break;
+ default:
+ fm_ereport_id = NXGE_FM_EREPORT_UNKNOWN;
+ }
+ break;
+ case WRITE_FAILED:
+ case READ_FAILED:
+ switch (block_id) {
+ case MIF_BLK_ID:
+ fm_ereport_id = NXGE_FM_EREPORT_MIF_ACCESS_FAIL;
+ break;
+ case ZCP_BLK_ID:
+ fm_ereport_id = NXGE_FM_EREPORT_ZCP_ACCESS_FAIL;
+ break;
+ case ESPC_BLK_ID:
+ fm_ereport_id =
+ NXGE_FM_EREPORT_ESPC_ACCESS_FAIL;
+ break;
+ case FFLP_BLK_ID:
+ fm_ereport_id =
+ NXGE_FM_EREPORT_FFLP_ACCESS_FAIL;
+ break;
+ default:
+ fm_ereport_id = NXGE_FM_EREPORT_UNKNOWN;
+ }
+ break;
+ case TXDMA_HW_STOP_FAILED:
+ case TXDMA_HW_RESUME_FAILED:
+ fm_ereport_id = NXGE_FM_EREPORT_TDMC_RESET_FAIL;
+ break;
+ }
+ }
+
+ fm_ereport_attr = nxge_fm_get_ereport_attr(fm_ereport_id);
+ if (fm_ereport_attr == NULL)
+ return;
+ class_name = fm_ereport_attr->eclass;
+
+ ena = fm_ena_generate(0, FM_ENA_FMT1);
+
+ if ((is_port == B_FALSE) && (is_chan == B_FALSE)) {
+ ddi_fm_ereport_post(nxgep->dip, class_name, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ NULL);
+ } else if ((is_port == B_TRUE) && (is_chan == B_FALSE)) {
+ ddi_fm_ereport_post(nxgep->dip, class_name, ena, DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, portn,
+ NULL);
+ } else if ((is_port == B_FALSE) && (is_chan == B_TRUE)) {
+ ddi_fm_ereport_post(nxgep->dip, class_name, ena, DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, chan,
+ NULL);
+ } else if ((is_port == B_TRUE) && (is_chan == B_TRUE)) {
+ ddi_fm_ereport_post(nxgep->dip, class_name, ena, DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, chan,
+ NULL);
+ }
+}
+
+static nxge_fm_ereport_attr_t *
+nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t ereport_id)
+{
+ nxge_fm_ereport_attr_t *attr;
+ uint8_t blk_id = ((ereport_id >> EREPORT_FM_ID_SHIFT) &
+ EREPORT_FM_ID_MASK);
+ uint8_t index = (ereport_id & EREPORT_INDEX_MASK);
+
+ switch (blk_id) {
+ case FM_SW_ID:
+ attr = &nxge_fm_ereport_sw[index];
+ break;
+ case FM_PCS_ID:
+ attr = &nxge_fm_ereport_pcs[index];
+ break;
+ case FM_TXMAC_ID:
+ attr = &nxge_fm_ereport_txmac[index];
+ break;
+ case FM_RXMAC_ID:
+ attr = &nxge_fm_ereport_rxmac[index];
+ break;
+ case FM_MIF_ID:
+ attr = &nxge_fm_ereport_mif[index];
+ break;
+ case FM_FFLP_ID:
+ attr = &nxge_fm_ereport_fflp[index];
+ break;
+ case FM_ZCP_ID:
+ attr = &nxge_fm_ereport_zcp[index];
+ break;
+ case FM_RXDMA_ID:
+ attr = &nxge_fm_ereport_rdmc[index];
+ break;
+ case FM_TXDMA_ID:
+ attr = &nxge_fm_ereport_tdmc[index];
+ break;
+ case FM_IPP_ID:
+ attr = &nxge_fm_ereport_ipp[index];
+ break;
+ case FM_TXC_ID:
+ attr = &nxge_fm_ereport_txc[index];
+ break;
+ case FM_ESPC_ID:
+ attr = &nxge_fm_ereport_espc[index];
+ break;
+ default:
+ attr = NULL;
+ }
+
+ return (attr);
+}
+
+static void
+nxge_fm_ereport(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
+ nxge_fm_ereport_attr_t *ereport)
+{
+ uint64_t ena;
+ char *eclass;
+ p_nxge_stats_t statsp;
+
+ eclass = ereport->eclass;
+ ena = fm_ena_generate(0, FM_ENA_FMT1);
+ statsp = nxgep->statsp;
+
+ if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities)) {
+ switch (ereport->index) {
+ case NXGE_FM_EREPORT_XPCS_LINK_DOWN:
+ case NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT:
+ case NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT:
+ case NXGE_FM_EREPORT_PCS_LINK_DOWN:
+ case NXGE_FM_EREPORT_PCS_REMOTE_FAULT:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_EOP_MISS:
+ case NXGE_FM_EREPORT_IPP_SOP_MISS:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_DFIFO_RD_PTR, DATA_TYPE_UINT16,
+ statsp->ipp_stats.errlog.dfifo_rd_ptr,
+ ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
+ statsp->ipp_stats.errlog.state_mach,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_DFIFO_UE:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_DFIFO_ENTRY, DATA_TYPE_UINT16,
+ nxgep->ipp.status.bits.w0.dfifo_ecc_err_idx,
+ ERNAME_DFIFO_SYNDROME, DATA_TYPE_UINT16,
+ statsp->ipp_stats.errlog.ecc_syndrome,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_PFIFO_ENTRY, DATA_TYPE_UINT8,
+ nxgep->ipp.status.bits.w0.pre_fifo_perr_idx,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_DFIFO_CE:
+ case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
+ case NXGE_FM_EREPORT_IPP_PFIFO_UND:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
+ statsp->ipp_stats.errlog.state_mach,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
+ case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_FFLP_TCAM_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_TCAM_ERR_LOG, DATA_TYPE_UINT32,
+ statsp->fflp_stats.errlog.tcam,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_VLANTAB_ERR_LOG, DATA_TYPE_UINT32,
+ statsp->fflp_stats.errlog.vlan,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR:
+ {
+ int rdc_grp;
+ hash_tbl_data_log_t hash_log;
+
+ for (rdc_grp = 0; rdc_grp < MAX_PARTITION; rdc_grp++) {
+ hash_log.value = nxgep->classifier.fflp_stats->
+ errlog.hash_pio[rdc_grp];
+ if (hash_log.bits.ldw.pio_err) {
+ ddi_fm_ereport_post(nxgep->dip, eclass,
+ ena, DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8,
+ FM_EREPORT_VERS0,
+ ERNAME_HASHTAB_ERR_LOG,
+ DATA_TYPE_UINT32,
+ nxgep->classifier.fflp_stats->
+ errlog.hash_pio[rdc_grp], NULL);
+ }
+ }
+ }
+ break;
+ case NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_HASHT_LOOKUP_ERR_LOG0, DATA_TYPE_UINT32,
+ statsp->fflp_stats.errlog. hash_lookup1,
+ ERNAME_HASHT_LOOKUP_ERR_LOG1, DATA_TYPE_UINT32,
+ statsp->fflp_stats.errlog.hash_lookup2,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_RDMC_DCF_ERR:
+ case NXGE_FM_EREPORT_RDMC_RBR_TMOUT:
+ case NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR:
+ case NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS:
+ case NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR:
+ case NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR:
+ case NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR:
+ case NXGE_FM_EREPORT_RDMC_CONFIG_ERR:
+ case NXGE_FM_EREPORT_RDMC_RCRINCON:
+ case NXGE_FM_EREPORT_RDMC_RCRFULL:
+ case NXGE_FM_EREPORT_RDMC_RBRFULL:
+ case NXGE_FM_EREPORT_RDMC_RBRLOGPAGE:
+ case NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE:
+ case NXGE_FM_EREPORT_RDMC_ID_MISMATCH:
+ case NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR:
+ case NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
+ case NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR:
+ {
+ uint32_t err_log;
+ if (ereport->index == NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
+ err_log = (uint32_t)statsp->
+ rdc_stats[err_chan].errlog.pre_par.value;
+ else
+ err_log = (uint32_t)statsp->
+ rdc_stats[err_chan].errlog.sha_par.value;
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
+ ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8,
+ err_log, NULL);
+ }
+ break;
+ case NXGE_FM_EREPORT_RDMC_COMPLETION_ERR:
+ {
+ uint8_t err_type;
+ err_type = statsp->
+ rdc_stats[err_chan].errlog.compl_err_type;
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
+ ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8,
+ err_type, NULL);
+ }
+ break;
+
+ case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
+ case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
+ case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
+ {
+ uint32_t sm;
+ sm = statsp->
+ zcp_stats.errlog.state_mach.bits.ldw.state;
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ sm, DATA_TYPE_UINT32,
+ NULL);
+ break;
+ }
+ case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8,
+ err_portn,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
+ case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
+ case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
+ case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
+ case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
+ case NXGE_FM_EREPORT_RXMAC_UNDERFLOW:
+ case NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP:
+ case NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP:
+ case NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP:
+ case NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP:
+ case NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP:
+ case NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
+ case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
+ case NXGE_FM_EREPORT_TDMC_NACK_PREF:
+ case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
+ case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
+ case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
+ case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
+ ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
+ statsp->
+ tdc_stats[err_chan].errlog.logl.value,
+ ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
+ statsp->tdc_stats[err_chan].errlog.logh.value,
+ DATA_TYPE_UINT32,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
+ case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_TXC_ROECC_ADDR, DATA_TYPE_UINT16,
+ statsp->txc_stats.errlog.ro_st.roecc.
+ bits.ldw.ecc_address,
+ ERNAME_TXC_ROECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.ro_st.d0.
+ bits.ldw.ro_ecc_data0,
+ ERNAME_TXC_ROECC_DATA1, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.ro_st.d1.
+ bits.ldw.ro_ecc_data1,
+ ERNAME_TXC_ROECC_DATA2, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.ro_st.d2.
+ bits.ldw.ro_ecc_data2,
+ ERNAME_TXC_ROECC_DATA3, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.ro_st.d3.
+ bits.ldw.ro_ecc_data3,
+ ERNAME_TXC_ROECC_DATA4, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.ro_st.d4.
+ bits.ldw.ro_ecc_data4,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TXC_REORDER_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_TXC_RO_STATE0, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.st0.value,
+ ERNAME_TXC_RO_STATE1, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.st1.value,
+ ERNAME_TXC_RO_STATE2, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.st2.value,
+ ERNAME_TXC_RO_STATE3, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.st3.value,
+ ERNAME_TXC_RO_STATE_CTL, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.ctl.value,
+ ERNAME_TXC_RO_TIDS, DATA_TYPE_UINT32,
+ (uint32_t)statsp->
+ txc_stats.errlog.ro_st.tids.value,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
+ case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ ERNAME_TXC_SFECC_ADDR, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.sfecc.
+ bits.ldw.ecc_address,
+ ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.d0.
+ bits.ldw.sf_ecc_data0,
+ ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.d1.
+ bits.ldw.sf_ecc_data1,
+ ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.d2.
+ bits.ldw.sf_ecc_data2,
+ ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.d3.
+ bits.ldw.sf_ecc_data3,
+ ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
+ statsp->txc_stats.errlog.sf_st.d4.
+ bits.ldw.sf_ecc_data4,
+ NULL);
+ break;
+ case NXGE_FM_EREPORT_TXMAC_UNDERFLOW:
+ case NXGE_FM_EREPORT_TXMAC_OVERFLOW:
+ case NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR:
+ case NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR:
+ case NXGE_FM_EREPORT_SW_INVALID_PORT_NUM:
+ case NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
+ case NXGE_FM_EREPORT_SW_INVALID_PARAM:
+ ddi_fm_ereport_post(nxgep->dip, eclass, ena,
+ DDI_NOSLEEP,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
+ NULL);
+ break;
+ }
+
+ }
+}
+
+void
+nxge_fm_report_error(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
+ nxge_fm_ereport_id_t fm_ereport_id)
+{
+ nxge_fm_ereport_attr_t *fm_ereport_attr;
+
+ fm_ereport_attr = nxge_fm_get_ereport_attr(fm_ereport_id);
+
+ if (fm_ereport_attr != NULL) {
+ nxge_fm_ereport(nxgep, err_portn, err_chan, fm_ereport_attr);
+ cmn_err(CE_NOTE, "!service_impact = %d\n",
+ fm_ereport_attr->impact);
+ ddi_fm_service_impact(nxgep->dip, fm_ereport_attr->impact);
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_fzc.c b/usr/src/uts/sun4v/io/nxge/nxge_fzc.c
new file mode 100644
index 0000000000..b9e357ca16
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_fzc.c
@@ -0,0 +1,1039 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nxge_impl.h>
+#include <npi_mac.h>
+#include <npi_rxdma.h>
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+static int nxge_herr2kerr(uint64_t);
+#endif
+
+/*
+ * The following interfaces are controlled by the
+ * function control registers. Some global registers
+ * are to be initialized by only byt one of the 2/4 functions.
+ * Use the test and set register.
+ */
+/*ARGSUSED*/
+nxge_status_t
+nxge_test_and_set(p_nxge_t nxgep, uint8_t tas)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if ((rs = npi_dev_func_sr_sr_get_set_clear(handle, tas))
+ != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_set_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t mpc)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_set_fzc_multi_part_ctl"));
+
+ /*
+ * In multi-partitioning, the partition manager
+ * who owns function zero should set this multi-partition
+ * control bit.
+ */
+ if (nxgep->use_partition && nxgep->function_num) {
+ return (NXGE_ERROR);
+ }
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if ((rs = npi_fzc_mpc_set(handle, mpc)) != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_set_fzc_multi_part_ctl"));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_set_fzc_multi_part_ctl"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_get_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t *mpc_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if ((rs = npi_fzc_mpc_get(handle, mpc_p)) != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_set_fzc_multi_part_ctl"));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
+
+ return (NXGE_OK);
+}
+
+/*
+ * System interrupt registers that are under function zero
+ * management.
+ */
+nxge_status_t
+nxge_fzc_intr_init(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_init"));
+
+ /* Configure the initial timer resolution */
+ if ((status = nxge_fzc_intr_tmres_set(nxgep)) != NXGE_OK) {
+ return (status);
+ }
+
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ /*
+ * Set up the logical device group's logical devices that
+ * the group owns.
+ */
+ if ((status = nxge_fzc_intr_ldg_num_set(nxgep))
+ != NXGE_OK) {
+ break;
+ }
+
+ /* Configure the system interrupt data */
+ if ((status = nxge_fzc_intr_sid_set(nxgep)) != NXGE_OK) {
+ break;
+ }
+
+ break;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_init"));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_fzc_intr_ldg_num_set(p_nxge_t nxgep)
+{
+ p_nxge_ldg_t ldgp;
+ p_nxge_ldv_t ldvp;
+ npi_handle_t handle;
+ int i, j;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_ldg_num_set"));
+
+ if (nxgep->ldgvp == NULL) {
+ return (NXGE_ERROR);
+ }
+
+ ldgp = nxgep->ldgvp->ldgp;
+ ldvp = nxgep->ldgvp->ldvp;
+ if (ldgp == NULL || ldvp == NULL) {
+ return (NXGE_ERROR);
+ }
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_fzc_intr_ldg_num_set "
+ "<== nxge_f(Neptune): # ldv %d "
+ "in group %d", ldgp->nldvs, ldgp->ldg));
+
+ for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
+ rs = npi_fzc_ldg_num_set(handle, ldvp->ldv,
+ ldvp->ldg_assigned);
+ if (rs != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_fzc_intr_ldg_num_set failed "
+ " rs 0x%x ldv %d ldg %d",
+ rs, ldvp->ldv, ldvp->ldg_assigned));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_fzc_intr_ldg_num_set OK "
+ " ldv %d ldg %d",
+ ldvp->ldv, ldvp->ldg_assigned));
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_ldg_num_set"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fzc_intr_tmres_set(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_tmrese_set"));
+ if (nxgep->ldgvp == NULL) {
+ return (NXGE_ERROR);
+ }
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if ((rs = npi_fzc_ldg_timer_res_set(handle, nxgep->ldgvp->tmres))) {
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_tmrese_set"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_fzc_intr_sid_set(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ p_nxge_ldg_t ldgp;
+ fzc_sid_t sid;
+ int i;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_sid_set"));
+ if (nxgep->ldgvp == NULL) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_fzc_intr_sid_set: no ldg"));
+ return (NXGE_ERROR);
+ }
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ ldgp = nxgep->ldgvp->ldgp;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_fzc_intr_sid_set: #int %d", nxgep->ldgvp->ldg_intrs));
+ for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
+ sid.ldg = ldgp->ldg;
+ sid.niu = B_FALSE;
+ sid.func = ldgp->func;
+ sid.vector = ldgp->vector;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_fzc_intr_sid_set(%d): func %d group %d "
+ "vector %d",
+ i, sid.func, sid.ldg, sid.vector));
+ rs = npi_fzc_sid_set(handle, sid);
+ if (rs != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_fzc_intr_sid_set:failed 0x%x",
+ rs));
+ return (NXGE_ERROR | rs);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_sid_set"));
+
+ return (NXGE_OK);
+
+}
+
+/*
+ * Receive DMA registers that are under function zero
+ * management.
+ */
+/*ARGSUSED*/
+nxge_status_t
+nxge_init_fzc_rxdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p)
+{
+ nxge_status_t status = NXGE_OK;
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_init_fzc_rxdma_channel"));
+
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ default:
+ /* Initialize the RXDMA logical pages */
+ status = nxge_init_fzc_rxdma_channel_pages(nxgep, channel,
+ rbr_p);
+ if (status != NXGE_OK) {
+ return (status);
+ }
+
+ break;
+
+#ifndef NIU_HV_WORKAROUND
+ case N2_NIU:
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_init_fzc_rxdma_channel: N2_NIU - call HV "
+ "set up logical pages"));
+ /* Initialize the RXDMA logical pages */
+ status = nxge_init_hv_fzc_rxdma_channel_pages(nxgep, channel,
+ rbr_p);
+ if (status != NXGE_OK) {
+ return (status);
+ }
+#endif
+ break;
+#else
+ case N2_NIU:
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to "
+ "set up logical pages"));
+ /* Initialize the RXDMA logical pages */
+ status = nxge_init_fzc_rxdma_channel_pages(nxgep, channel,
+ rbr_p);
+ if (status != NXGE_OK) {
+ return (status);
+ }
+
+ break;
+#endif
+ }
+
+ /* Configure RED parameters */
+ status = nxge_init_fzc_rxdma_channel_red(nxgep, channel, rcr_p);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_init_fzc_rxdma_channel"));
+ return (status);
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_init_fzc_rxdma_channel_pages(p_nxge_t nxgep,
+ uint16_t channel, p_rx_rbr_ring_t rbrp)
+{
+ npi_handle_t handle;
+ dma_log_page_t cfg;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_rxdma_channel_pages"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Initialize logical page 1.
+ */
+ cfg.func_num = nxgep->function_num;
+ cfg.page_num = 0;
+ cfg.valid = rbrp->page_valid.bits.ldw.page0;
+ cfg.value = rbrp->page_value_1.value;
+ cfg.mask = rbrp->page_mask_1.value;
+ cfg.reloc = rbrp->page_reloc_1.value;
+ rs = npi_rxdma_cfg_logical_page(handle, channel,
+ (p_dma_log_page_t)&cfg);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /*
+ * Initialize logical page 2.
+ */
+ cfg.page_num = 1;
+ cfg.valid = rbrp->page_valid.bits.ldw.page1;
+ cfg.value = rbrp->page_value_2.value;
+ cfg.mask = rbrp->page_mask_2.value;
+ cfg.reloc = rbrp->page_reloc_2.value;
+
+ rs = npi_rxdma_cfg_logical_page(handle, channel, &cfg);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Initialize the page handle */
+ rs = npi_rxdma_cfg_logical_page_handle(handle, channel,
+ rbrp->page_hdl.bits.ldw.handle);
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_rxdma_channel_pages"));
+
+ return (NXGE_OK);
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_init_fzc_rxdma_channel_red(p_nxge_t nxgep,
+ uint16_t channel, p_rx_rcr_ring_t rcr_p)
+{
+ npi_handle_t handle;
+ rdc_red_para_t red;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_channel_red"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ red.value = 0;
+ red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT;
+ red.bits.ldw.thre = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
+ red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT;
+ red.bits.ldw.thre_sync = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))",
+ red.bits.ldw.thre_sync,
+ red.bits.ldw.thre_sync));
+
+ rs = npi_rxdma_cfg_wred_param(handle, channel, &red);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_rxdma_channel_red"));
+
+ return (NXGE_OK);
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_init_fzc_txdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p, p_tx_mbox_t mbox_p)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_txdma_channel"));
+
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ default:
+ /* Initialize the TXDMA logical pages */
+ (void) nxge_init_fzc_txdma_channel_pages(nxgep, channel,
+ tx_ring_p);
+ break;
+
+#ifndef NIU_HV_WORKAROUND
+ case N2_NIU:
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_txdma_channel "
+ "N2_NIU: call HV to set up txdma logical pages"));
+ status = nxge_init_hv_fzc_txdma_channel_pages(nxgep, channel,
+ tx_ring_p);
+ if (status != NXGE_OK) {
+ return (status);
+ }
+#endif
+ break;
+#else
+ case N2_NIU:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_txdma_channel "
+ "N2_NIU: NEED to set up txdma logical pages"));
+ /* Initialize the TXDMA logical pages */
+ (void) nxge_init_fzc_txdma_channel_pages(nxgep, channel,
+ tx_ring_p);
+ break;
+#endif
+ }
+
+ /*
+ * Configure Transmit DRR Weight parameters
+ * (It actually programs the TXC max burst register).
+ */
+ (void) nxge_init_fzc_txdma_channel_drr(nxgep, channel, tx_ring_p);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_txdma_channel"));
+ return (status);
+}
+
+nxge_status_t
+nxge_init_fzc_common(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ (void) nxge_init_fzc_rx_common(nxgep);
+
+ return (status);
+}
+
+nxge_status_t
+nxge_init_fzc_rx_common(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ clock_t lbolt;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rx_common"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if (!handle.regp) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_rx_common null ptr"));
+ return (NXGE_ERROR);
+ }
+
+ /*
+ * Configure the rxdma clock divider
+ * This is the granularity counter based on
+ * the hardware system clock (i.e. 300 Mhz) and
+ * it is running around 3 nanoseconds.
+ * So, set the clock divider counter to 1000 to get
+ * microsecond granularity.
+ * For example, for a 3 microsecond timeout, the timeout
+ * will be set to 1.
+ */
+ rs = npi_rxdma_cfg_clock_div_set(handle, RXDMA_CK_DIV_DEFAULT);
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+#if defined(__i386)
+ rs = npi_rxdma_cfg_32bitmode_enable(handle);
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ rs = npi_txdma_mode32_set(handle, B_TRUE);
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+#endif
+
+ /*
+ * Enable WRED and program an initial value.
+ * Use time to set the initial random number.
+ */
+ (void) drv_getparm(LBOLT, &lbolt);
+ rs = npi_rxdma_cfg_red_rand_init(handle, (uint16_t)lbolt);
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+ /* Initialize the RDC tables for each group */
+ status = nxge_init_fzc_rdc_tbl(nxgep);
+
+
+ /* Ethernet Timeout Counter (?) */
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_rx_common:status 0x%08x", status));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_init_fzc_rdc_tbl(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+ uint8_t grp_tbl_id;
+ int ngrps;
+ int i;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rdc_tbl"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ grp_tbl_id = p_cfgp->start_rdc_grpid;
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[0];
+ ngrps = p_cfgp->max_rdc_grpids;
+ for (i = 0; i < ngrps; i++, rdc_grp_p++) {
+ rs = npi_rxdma_cfg_rdc_table(handle, grp_tbl_id++,
+ rdc_grp_p->rdc);
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ break;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_rdc_tbl"));
+ return (status);
+}
+
+nxge_status_t
+nxge_init_fzc_rxdma_port(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ p_nxge_dma_pt_cfg_t p_all_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ hostinfo_t hostinfo;
+ int i;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_port"));
+
+ p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Initialize the port scheduler DRR weight.
+ * npi_rxdma_cfg_port_ddr_weight();
+ */
+
+ if (nxgep->niu_type == NEPTUNE) {
+ if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
+ (nxgep->mac.portmode == PORT_1G_FIBER)) {
+ rs = npi_rxdma_cfg_port_ddr_weight(handle,
+ nxgep->function_num,
+ NXGE_RX_DRR_WT_1G);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ }
+ }
+
+ /* Program the default RDC of a port */
+ rs = npi_rxdma_cfg_default_port_rdc(handle, nxgep->function_num,
+ p_cfgp->def_rdc);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /*
+ * Configure the MAC host info table with RDC tables
+ */
+ hostinfo.value = 0;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ for (i = 0; i < p_cfgp->max_macs; i++) {
+ hostinfo.bits.w0.rdc_tbl_num = p_cfgp->start_rdc_grpid;
+ hostinfo.bits.w0.mac_pref = p_cfgp->mac_pref;
+ if (p_class_cfgp->mac_host_info[i].flag) {
+ hostinfo.bits.w0.rdc_tbl_num =
+ p_class_cfgp->mac_host_info[i].rdctbl;
+ hostinfo.bits.w0.mac_pref =
+ p_class_cfgp->mac_host_info[i].mpr_npr;
+ }
+
+ rs = npi_mac_hostinfo_entry(handle, OP_SET,
+ nxgep->function_num, i, &hostinfo);
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_rxdma_port rs 0x%08x", rs));
+
+ return (NXGE_OK);
+
+}
+
+nxge_status_t
+nxge_fzc_dmc_def_port_rdc(p_nxge_t nxgep, uint8_t port, uint16_t rdc)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ rs = npi_rxdma_cfg_default_port_rdc(nxgep->npi_reg_handle,
+ port, rdc);
+ if (rs & NPI_FAILURE)
+ return (NXGE_ERROR | rs);
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_init_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p)
+{
+ npi_handle_t handle;
+ dma_log_page_t cfg;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_init_fzc_txdma_channel_pages"));
+
+#ifndef NIU_HV_WORKAROUND
+ if (nxgep->niu_type == N2_NIU) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_txdma_channel_pages: "
+ "N2_NIU: no need to set txdma logical pages"));
+ return (NXGE_OK);
+ }
+#else
+ if (nxgep->niu_type == N2_NIU) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_fzc_txdma_channel_pages: "
+ "N2_NIU: NEED to set txdma logical pages"));
+ }
+#endif
+
+ /*
+ * Initialize logical page 1.
+ */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ cfg.func_num = nxgep->function_num;
+ cfg.page_num = 0;
+ cfg.valid = tx_ring_p->page_valid.bits.ldw.page0;
+ cfg.value = tx_ring_p->page_value_1.value;
+ cfg.mask = tx_ring_p->page_mask_1.value;
+ cfg.reloc = tx_ring_p->page_reloc_1.value;
+
+ rs = npi_txdma_log_page_set(handle, channel,
+ (p_dma_log_page_t)&cfg);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /*
+ * Initialize logical page 2.
+ */
+ cfg.page_num = 1;
+ cfg.valid = tx_ring_p->page_valid.bits.ldw.page1;
+ cfg.value = tx_ring_p->page_value_2.value;
+ cfg.mask = tx_ring_p->page_mask_2.value;
+ cfg.reloc = tx_ring_p->page_reloc_2.value;
+
+ rs = npi_txdma_log_page_set(handle, channel, &cfg);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Initialize the page handle */
+ rs = npi_txdma_log_page_handle_set(handle, channel,
+ &tx_ring_p->page_hdl);
+
+ if (rs == NPI_SUCCESS) {
+ return (NXGE_OK);
+ } else {
+ return (NXGE_ERROR | rs);
+ }
+}
+
+
+nxge_status_t
+nxge_init_fzc_txdma_channel_drr(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_txc_dma_max_burst_set(handle, channel,
+ tx_ring_p->max_burst.value);
+ if (rs == NPI_SUCCESS) {
+ return (NXGE_OK);
+ } else {
+ return (NXGE_ERROR | rs);
+ }
+}
+
+nxge_status_t
+nxge_fzc_sys_err_mask_set(p_nxge_t nxgep, uint64_t mask)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_fzc_sys_err_mask_set(handle, mask);
+ if (rs == NPI_SUCCESS) {
+ return (NXGE_OK);
+ } else {
+ return (NXGE_ERROR | rs);
+ }
+}
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+nxge_status_t
+nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p)
+{
+ int err;
+ uint64_t hverr;
+#ifdef DEBUG
+ uint64_t ra, size;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_init_hv_fzc_txdma_channel_pages"));
+
+ if (tx_ring_p->hv_set) {
+ return (NXGE_OK);
+ }
+
+ /*
+ * Initialize logical page 1 for data buffers.
+ */
+ hverr = hv_niu_tx_logical_page_conf((uint64_t)channel,
+ (uint64_t)0,
+ tx_ring_p->hv_tx_buf_base_ioaddr_pp,
+ tx_ring_p->hv_tx_buf_ioaddr_size);
+
+ err = (nxge_status_t)nxge_herr2kerr(hverr);
+ if (err != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d "
+ "error status 0x%x "
+ "(page 0 data buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ tx_ring_p->hv_tx_buf_base_ioaddr_pp,
+ tx_ring_p->hv_tx_buf_ioaddr_size));
+ return (NXGE_ERROR | err);
+ }
+
+#ifdef DEBUG
+ ra = size = 0;
+ hverr = hv_niu_tx_logical_page_info((uint64_t)channel,
+ (uint64_t)0,
+ &ra,
+ &size);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
+ "ok status 0x%x "
+ "(page 0 data buf) hverr 0x%llx "
+ "set ioaddr_pp $%p "
+ "set size 0x%llx "
+ "get ra ioaddr_pp $%p "
+ "get size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ tx_ring_p->hv_tx_buf_base_ioaddr_pp,
+ tx_ring_p->hv_tx_buf_ioaddr_size,
+ ra,
+ size));
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
+ "(page 0 data buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ hverr,
+ tx_ring_p->hv_tx_buf_base_ioaddr_pp,
+ tx_ring_p->hv_tx_buf_ioaddr_size));
+
+ /*
+ * Initialize logical page 2 for control buffers.
+ */
+ hverr = hv_niu_tx_logical_page_conf((uint64_t)channel,
+ (uint64_t)1,
+ tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
+ tx_ring_p->hv_tx_cntl_ioaddr_size);
+
+ err = (nxge_status_t)nxge_herr2kerr(hverr);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d"
+ "ok status 0x%x "
+ "(page 1 cntl buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
+ tx_ring_p->hv_tx_cntl_ioaddr_size));
+
+ if (err != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d"
+ "error status 0x%x "
+ "(page 1 cntl buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
+ tx_ring_p->hv_tx_cntl_ioaddr_size));
+ return (NXGE_ERROR | err);
+ }
+
+#ifdef DEBUG
+ ra = size = 0;
+ hverr = hv_niu_tx_logical_page_info((uint64_t)channel,
+ (uint64_t)1,
+ &ra,
+ &size);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
+ "(page 1 cntl buf) hverr 0x%llx "
+ "set ioaddr_pp $%p "
+ "set size 0x%llx "
+ "get ra ioaddr_pp $%p "
+ "get size 0x%llx ",
+ channel,
+ hverr,
+ tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
+ tx_ring_p->hv_tx_cntl_ioaddr_size,
+ ra,
+ size));
+#endif
+
+ tx_ring_p->hv_set = B_TRUE;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_init_hv_fzc_txdma_channel_pages"));
+
+ return (NXGE_OK);
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t nxgep,
+ uint16_t channel, p_rx_rbr_ring_t rbrp)
+{
+ int err;
+ uint64_t hverr;
+#ifdef DEBUG
+ uint64_t ra, size;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_init_hv_fzc_rxdma_channel_pages"));
+
+ if (rbrp->hv_set) {
+ return (NXGE_OK);
+ }
+
+ /* Initialize data buffers for page 0 */
+ hverr = hv_niu_rx_logical_page_conf((uint64_t)channel,
+ (uint64_t)0,
+ rbrp->hv_rx_buf_base_ioaddr_pp,
+ rbrp->hv_rx_buf_ioaddr_size);
+ err = (nxge_status_t)nxge_herr2kerr(hverr);
+ if (err != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
+ "error status 0x%x "
+ "(page 0 data buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ rbrp->hv_rx_buf_base_ioaddr_pp,
+ rbrp->hv_rx_buf_ioaddr_size));
+
+ return (NXGE_ERROR | err);
+ }
+
+#ifdef DEBUG
+ ra = size = 0;
+ (void) hv_niu_rx_logical_page_info((uint64_t)channel,
+ (uint64_t)0,
+ &ra,
+ &size);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
+ "ok status 0x%x "
+ "(page 0 data buf) hverr 0x%llx "
+ "set databuf ioaddr_pp $%p "
+ "set databuf size 0x%llx "
+ "get databuf ra ioaddr_pp %p "
+ "get databuf size 0x%llx",
+ channel,
+ err,
+ hverr,
+ rbrp->hv_rx_buf_base_ioaddr_pp,
+ rbrp->hv_rx_buf_ioaddr_size,
+ ra,
+ size));
+#endif
+
+ /* Initialize control buffers for logical page 1. */
+ hverr = hv_niu_rx_logical_page_conf((uint64_t)channel,
+ (uint64_t)1,
+ rbrp->hv_rx_cntl_base_ioaddr_pp,
+ rbrp->hv_rx_cntl_ioaddr_size);
+
+ err = (nxge_status_t)nxge_herr2kerr(hverr);
+ if (err != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
+ "error status 0x%x "
+ "(page 1 cntl buf) hverr 0x%llx "
+ "ioaddr_pp $%p "
+ "size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ rbrp->hv_rx_buf_base_ioaddr_pp,
+ rbrp->hv_rx_buf_ioaddr_size));
+
+ return (NXGE_ERROR | err);
+ }
+
+#ifdef DEBUG
+ ra = size = 0;
+ (void) hv_niu_rx_logical_page_info((uint64_t)channel,
+ (uint64_t)1,
+ &ra,
+ &size);
+
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
+ "error status 0x%x "
+ "(page 1 cntl buf) hverr 0x%llx "
+ "set cntl ioaddr_pp $%p "
+ "set cntl size 0x%llx "
+ "get cntl ioaddr_pp $%p "
+ "get cntl size 0x%llx ",
+ channel,
+ err,
+ hverr,
+ rbrp->hv_rx_cntl_base_ioaddr_pp,
+ rbrp->hv_rx_cntl_ioaddr_size,
+ ra,
+ size));
+#endif
+
+ rbrp->hv_set = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_init_hv_fzc_rxdma_channel_pages"));
+
+ return (NXGE_OK);
+}
+
+/*
+ * Map hypervisor error code to errno. Only
+ * H_ENORADDR, H_EBADALIGN and H_EINVAL are meaningful
+ * for niu driver. Any other error codes are mapped to EINVAL.
+ */
+static int
+nxge_herr2kerr(uint64_t hv_errcode)
+{
+ int s_errcode;
+
+ switch (hv_errcode) {
+ case H_ENORADDR:
+ case H_EBADALIGN:
+ s_errcode = EFAULT;
+ break;
+ case H_EOK:
+ s_errcode = 0;
+ break;
+ default:
+ s_errcode = EINVAL;
+ break;
+ }
+ return (s_errcode);
+}
+
+#endif /* sun4v and NIU_LP_WORKAROUND */
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_hcall.s b/usr/src/uts/sun4v/io/nxge/nxge_hcall.s
new file mode 100644
index 0000000000..3ba5449bfc
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_hcall.s
@@ -0,0 +1,114 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Hypervisor calls called by niu leaf driver.
+*/
+
+#include <sys/asm_linkage.h>
+#include <sys/hypervisor_api.h>
+#include <sys/nxge/nxge_impl.h>
+
+#if defined(lint) || defined(__lint)
+
+/*ARGSUSED*/
+uint64_t
+hv_niu_rx_logical_page_conf(uint64_t chidx, uint64_t pgidx,
+ uint64_t raddr, uint64_t size)
+{ return (0); }
+
+/*ARGSUSED*/
+uint64_t
+hv_niu_rx_logical_page_info(uint64_t chidx, uint64_t pgidx,
+ uint64_t *raddr, uint64_t *size)
+{ return (0); }
+
+/*ARGSUSED*/
+uint64_t
+hv_niu_tx_logical_page_conf(uint64_t chidx, uint64_t pgidx,
+ uint64_t raddr, uint64_t size)
+{ return (0); }
+
+/*ARGSUSED*/
+uint64_t
+hv_niu_tx_logical_page_info(uint64_t chidx, uint64_t pgidx,
+ uint64_t *raddr, uint64_t *size)
+{ return (0); }
+
+#else /* lint || __lint */
+
+ /*
+ * hv_niu_rx_logical_page_conf(uint64_t chidx, uint64_t pgidx,
+ * uint64_t raddr, uint64_t size)
+ */
+ ENTRY(hv_niu_rx_logical_page_conf)
+ mov N2NIU_RX_LP_CONF, %o5
+ ta FAST_TRAP
+ retl
+ nop
+ SET_SIZE(hv_niu_rx_logical_page_conf)
+
+ /*
+ * hv_niu_rx_logical_page_info(uint64_t chidx, uint64_t pgidx,
+ * uint64_t *raddr, uint64_t *size)
+ */
+ ENTRY(hv_niu_rx_logical_page_info)
+ mov %o2, %g1
+ mov %o3, %g2
+ mov N2NIU_RX_LP_INFO, %o5
+ ta FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ stx %o2, [%g2]
+ SET_SIZE(hv_niu_rx_logical_page_info)
+
+ /*
+ * hv_niu_tx_logical_page_conf(uint64_t chidx, uint64_t pgidx,
+ * uint64_t raddr, uint64_t size)
+ */
+ ENTRY(hv_niu_tx_logical_page_conf)
+ mov N2NIU_TX_LP_CONF, %o5
+ ta FAST_TRAP
+ retl
+ nop
+ SET_SIZE(hv_niu_tx_logical_page_conf)
+
+ /*
+ * hv_niu_tx_logical_page_info(uint64_t chidx, uint64_t pgidx,
+ * uint64_t *raddr, uint64_t *size)
+ */
+ ENTRY(hv_niu_tx_logical_page_info)
+ mov %o2, %g1
+ mov %o3, %g2
+ mov N2NIU_TX_LP_INFO, %o5
+ ta FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ stx %o2, [%g2]
+ SET_SIZE(hv_niu_tx_logical_page_info)
+
+#endif /* lint || __lint */
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_hw.c b/usr/src/uts/sun4v/io/nxge/nxge_hw.c
new file mode 100644
index 0000000000..3b41306dc1
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_hw.c
@@ -0,0 +1,1047 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+
+/*
+ * Tunable Receive Completion Ring Configuration B parameters.
+ */
+uint16_t nxge_rx_pkt_thres; /* 16 bits */
+uint8_t nxge_rx_pkt_timeout; /* 6 bits based on DMA clock divider */
+
+lb_property_t lb_normal =
+ {normal, "normal", nxge_lb_normal};
+lb_property_t lb_external10g =
+ {external, "external10g", nxge_lb_ext10g};
+lb_property_t lb_external1000 =
+ {external, "external1000", nxge_lb_ext1000};
+lb_property_t lb_external100 =
+ {external, "external100", nxge_lb_ext100};
+lb_property_t lb_external10 =
+ {external, "external10", nxge_lb_ext10};
+lb_property_t lb_phy10g =
+ {internal, "phy10g", nxge_lb_phy10g};
+lb_property_t lb_phy1000 =
+ {internal, "phy1000", nxge_lb_phy1000};
+lb_property_t lb_phy =
+ {internal, "phy", nxge_lb_phy};
+lb_property_t lb_serdes10g =
+ {internal, "serdes10g", nxge_lb_serdes10g};
+lb_property_t lb_serdes1000 =
+ {internal, "serdes", nxge_lb_serdes1000};
+lb_property_t lb_mac10g =
+ {internal, "mac10g", nxge_lb_mac10g};
+lb_property_t lb_mac1000 =
+ {internal, "mac1000", nxge_lb_mac1000};
+lb_property_t lb_mac =
+ {internal, "mac10/100", nxge_lb_mac};
+
+uint32_t nxge_lb_dbg = 1;
+void nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp);
+void nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp);
+
+extern uint32_t nxge_rx_mode;
+extern uint32_t nxge_jumbo_mtu;
+extern boolean_t nxge_jumbo_enable;
+
+static void nxge_rtrace_ioctl(p_nxge_t, queue_t *,
+ mblk_t *, struct iocblk *);
+
+void
+nxge_global_reset(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_global_reset"));
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_intr_hw_disable(nxgep);
+
+ if ((nxgep->suspended) ||
+ ((nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g))) {
+ (void) nxge_link_init(nxgep);
+ }
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+
+ (void) nxge_mac_init(nxgep);
+
+ (void) nxge_intr_hw_enable(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_global_reset"));
+}
+
+void
+nxge_hw_id_init(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_id_init"));
+
+ /*
+ * Set up initial hardware parameters required such as mac mtu size.
+ */
+ nxgep->mac.is_jumbo = B_FALSE;
+ nxgep->mac.maxframesize = NXGE_MTU_DEFAULT_MAX; /* 1522 */
+ if (nxge_jumbo_enable) {
+ nxgep->mac.maxframesize = nxge_jumbo_mtu +
+ sizeof (ether_header_t) + ETHERFCSL;
+ nxgep->mac.is_jumbo = B_TRUE;
+ }
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_hw_id_init: maxframesize %d",
+ nxgep->mac.maxframesize));
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init"));
+
+}
+
+void
+nxge_hw_init_niu_common(p_nxge_t nxgep)
+{
+ p_nxge_hw_list_t hw_p;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_init_niu_common"));
+
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ return;
+ }
+
+ MUTEX_ENTER(&hw_p->nxge_cfg_lock);
+ if (hw_p->flags & COMMON_INIT_DONE) {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "nxge_hw_init_niu_common"
+ " already done for dip $%p function %d exiting",
+ hw_p->parent_devp,
+ nxgep->function_num));
+ MUTEX_EXIT(&hw_p->nxge_cfg_lock);
+ return;
+ }
+
+ hw_p->flags = COMMON_INIT_START;
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
+ " Started for device id %x with function %d",
+ hw_p->parent_devp,
+ nxgep->function_num));
+
+ (void) nxge_fflp_hw_reset(nxgep); /* per neptune common block init */
+ hw_p->flags = COMMON_INIT_DONE;
+ MUTEX_EXIT(&hw_p->nxge_cfg_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
+ " Done for device id %x with function %d",
+ hw_p->parent_devp,
+ nxgep->function_num));
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_init_niu_common"));
+}
+
+uint_t
+nxge_intr(void *arg1, void *arg2)
+{
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+ uint_t serviced = DDI_INTR_UNCLAIMED;
+ uint8_t ldv;
+ npi_handle_t handle;
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldg_t ldgp, t_ldgp;
+ p_nxge_ldv_t t_ldvp;
+ uint64_t vector0 = 0, vector1 = 0, vector2 = 0;
+ int i, j, nldvs, nintrs = 1;
+ npi_status_t rs = NPI_SUCCESS;
+
+ /* DDI interface returns second arg as NULL (n2 niumx driver) !!! */
+ if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
+ nxgep = ldvp->nxgep;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr"));
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ NXGE_ERROR_MSG((nxgep, INT_CTL,
+ "<== nxge_intr: not initialized 0x%x",
+ serviced));
+
+ return (serviced);
+ }
+
+ ldgvp = nxgep->ldgvp;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: ldgvp $%p",
+ ldgvp));
+ if (ldvp == NULL && ldgvp) {
+ t_ldvp = ldvp = ldgvp->ldvp;
+ }
+ if (ldvp) {
+ ldgp = t_ldgp = ldvp->ldgp;
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
+ "ldgvp $%p ldvp $%p ldgp $%p",
+ ldgvp, ldvp, ldgp));
+ if (ldgvp == NULL || ldvp == NULL || ldgp == NULL) {
+ NXGE_ERROR_MSG((nxgep, INT_CTL, "==> nxge_intr: "
+ "ldgvp $%p ldvp $%p ldgp $%p",
+ ldgvp, ldvp, ldgp));
+ NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_intr: not ready"));
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ /*
+ * This interrupt handler will have to go through
+ * all the logical devices to find out which
+ * logical device interrupts us and then call
+ * its handler to process the events.
+ */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ t_ldgp = ldgp;
+ t_ldvp = ldgp->ldvp;
+
+ nldvs = ldgp->nldvs;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: #ldvs %d #intrs %d",
+ nldvs, ldgvp->ldg_intrs));
+
+ serviced = DDI_INTR_CLAIMED;
+ for (i = 0; i < nintrs; i++, t_ldgp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr(%d): #ldvs %d "
+ " #intrs %d", i, nldvs, nintrs));
+ /* Get this group's flag bits. */
+ t_ldgp->interrupted = B_FALSE;
+ rs = npi_ldsv_ldfs_get(handle, t_ldgp->ldg,
+ &vector0, &vector1, &vector2);
+ if (rs) {
+ continue;
+ }
+ if (!vector0 && !vector1 && !vector2) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
+ "no interrupts on group %d", t_ldgp->ldg));
+ continue;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
+ "vector0 0x%llx vector1 0x%llx vector2 0x%llx",
+ vector0, vector1, vector2));
+ t_ldgp->interrupted = B_TRUE;
+ nldvs = t_ldgp->nldvs;
+ for (j = 0; j < nldvs; j++, t_ldvp++) {
+ /*
+ * Call device's handler if flag bits are on.
+ */
+ ldv = t_ldvp->ldv;
+ if (((ldv < NXGE_MAC_LD_START) &&
+ (LDV_ON(ldv, vector0) |
+ (LDV_ON(ldv, vector1)))) ||
+ (ldv >= NXGE_MAC_LD_START &&
+ ((LDV2_ON_1(ldv, vector2)) ||
+ (LDV2_ON_2(ldv, vector2))))) {
+ (void) (t_ldvp->ldv_intr_handler)(
+ (caddr_t)t_ldvp, arg2);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr: "
+ "calling device %d #ldvs %d #intrs %d",
+ j, nldvs, nintrs));
+ }
+ }
+ }
+
+ t_ldgp = ldgp;
+ for (i = 0; i < nintrs; i++, t_ldgp++) {
+ /* rearm group interrupts */
+ if (t_ldgp->interrupted) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: arm "
+ "group %d", t_ldgp->ldg));
+ (void) npi_intr_ldg_mgmt_set(handle, t_ldgp->ldg,
+ t_ldgp->arm, t_ldgp->ldg_timer);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr: serviced 0x%x",
+ serviced));
+ return (serviced);
+}
+
+uint_t
+nxge_syserr_intr(void *arg1, void *arg2)
+{
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+ p_nxge_ldg_t ldgp = NULL;
+ npi_handle_t handle;
+ sys_err_stat_t estat;
+ uint_t serviced = DDI_INTR_UNCLAIMED;
+
+ if (arg1 == NULL && arg2 == NULL) {
+ return (serviced);
+ }
+ if (arg2 == NULL || ((ldvp != NULL && (void *)ldvp->nxgep != arg2))) {
+ if (ldvp != NULL) {
+ nxgep = ldvp->nxgep;
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
+ "==> nxge_syserr_intr: arg2 $%p arg1 $%p",
+ nxgep, ldvp));
+ if (ldvp != NULL && ldvp->use_timer == B_FALSE) {
+ ldgp = ldvp->ldgp;
+ if (ldgp == NULL) {
+ NXGE_ERROR_MSG((nxgep, SYSERR_CTL,
+ "<== nxge_syserrintr(no logical group): "
+ "arg2 $%p arg1 $%p",
+ nxgep, ldvp));
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ /*
+ * Get the logical device state if the function uses interrupt.
+ */
+ }
+
+ /* This interrupt handler is for system error interrupts. */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ estat.value = 0;
+ (void) npi_fzc_sys_err_stat_get(handle, &estat);
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
+ "==> nxge_syserr_intr: device error 0x%016llx",
+ estat.value));
+
+ if (estat.bits.ldw.smx) {
+ /* SMX */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - SMX"));
+ } else if (estat.bits.ldw.mac) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - MAC"));
+ /*
+ * There is nothing to be done here. All MAC errors
+ * go to per MAC port interrupt. MIF interrupt is
+ * the only MAC sub-block that can generate status
+ * here. MIF status reported will be ignored here.
+ * It is checked by per port timer instead.
+ */
+ } else if (estat.bits.ldw.ipp) {
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - IPP"));
+ (void) nxge_ipp_handle_sys_errors(nxgep);
+ } else if (estat.bits.ldw.zcp) {
+ /* ZCP */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - ZCP"));
+ (void) nxge_zcp_handle_sys_errors(nxgep);
+ } else if (estat.bits.ldw.tdmc) {
+ /* TDMC */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - TDMC"));
+ /*
+ * There is no TDMC system errors defined in the PRM.
+ * All TDMC channel specific errors are reported on
+ * a per channel basis.
+ */
+ } else if (estat.bits.ldw.rdmc) {
+ /* RDMC */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - RDMC"));
+ (void) nxge_rxdma_handle_sys_errors(nxgep);
+ } else if (estat.bits.ldw.txc) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - TXC"));
+ (void) nxge_txc_handle_sys_errors(nxgep);
+ } else if ((nxgep->niu_type != N2_NIU) && estat.bits.ldw.peu) {
+ /* PCI-E */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - PCI-E"));
+ } else if (estat.bits.ldw.meta1) {
+ /* META1 */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - META1"));
+ } else if (estat.bits.ldw.meta2) {
+ /* META2 */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - META2"));
+ } else if (estat.bits.ldw.fflp) {
+ /* FFLP */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_syserr_intr: device error - FFLP"));
+ (void) nxge_fflp_handle_sys_errors(nxgep);
+ }
+ serviced = DDI_INTR_CLAIMED;
+
+ if (ldgp != NULL && ldvp != NULL && ldgp->nldvs == 1 &&
+ !ldvp->use_timer) {
+ (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ B_TRUE, ldgp->ldg_timer);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_syserr_intr"));
+ return (serviced);
+}
+
+void
+nxge_intr_hw_enable(p_nxge_t nxgep)
+{
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_enable"));
+
+ (void) nxge_intr_mask_mgmt_set(nxgep, B_TRUE);
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_enable"));
+}
+
+void
+nxge_intr_hw_disable(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_disable"));
+
+ (void) nxge_intr_mask_mgmt_set(nxgep, B_FALSE);
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_disable"));
+}
+
+
+void
+nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ uint8_t channel;
+ npi_handle_t handle;
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldv_t ldvp;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_hw_blank"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ if ((ldgvp = nxgep->ldgvp) == NULL) {
+ NXGE_ERROR_MSG((nxgep, INT_CTL,
+ "<== nxge_rx_hw_blank (not enabled)"));
+ return;
+ }
+ ldvp = nxgep->ldgvp->ldvp;
+ if (ldvp == NULL) {
+ return;
+ }
+ for (i = 0; i < ldgvp->nldvs; i++, ldvp++) {
+ if (ldvp->is_rxdma) {
+ channel = ldvp->channel;
+ (void) npi_rxdma_cfg_rdc_rcr_threshold(handle,
+ channel, count);
+ (void) npi_rxdma_cfg_rdc_rcr_timeout(handle,
+ channel, ticks);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_hw_blank"));
+}
+
+void
+nxge_hw_stop(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_stop"));
+
+ (void) nxge_tx_mac_disable(nxgep);
+ (void) nxge_rx_mac_disable(nxgep);
+ (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
+ (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_stop"));
+}
+
+void
+nxge_hw_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
+{
+ int cmd;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_hw_ioctl"));
+
+ if (nxgep == NULL) {
+ miocnak(wq, mp, 0, EINVAL);
+ return;
+ }
+
+ iocp->ioc_error = 0;
+ cmd = iocp->ioc_cmd;
+
+ switch (cmd) {
+ default:
+ miocnak(wq, mp, 0, EINVAL);
+ return;
+
+ case NXGE_GET_MII:
+ nxge_get_mii(nxgep, mp->b_cont);
+ miocack(wq, mp, sizeof (uint16_t), 0);
+ break;
+
+ case NXGE_PUT_MII:
+ nxge_put_mii(nxgep, mp->b_cont);
+ miocack(wq, mp, 0, 0);
+ break;
+
+ case NXGE_GET64:
+ nxge_get64(nxgep, mp->b_cont);
+ miocack(wq, mp, sizeof (uint32_t), 0);
+ break;
+
+ case NXGE_PUT64:
+ nxge_put64(nxgep, mp->b_cont);
+ miocack(wq, mp, 0, 0);
+ break;
+
+ case NXGE_PUT_TCAM:
+ nxge_put_tcam(nxgep, mp->b_cont);
+ miocack(wq, mp, 0, 0);
+ break;
+
+ case NXGE_GET_TCAM:
+ nxge_get_tcam(nxgep, mp->b_cont);
+ miocack(wq, mp, 0, 0);
+ break;
+
+ case NXGE_TX_REGS_DUMP:
+ nxge_txdma_regs_dump_channels(nxgep);
+ miocack(wq, mp, 0, 0);
+ break;
+ case NXGE_RX_REGS_DUMP:
+ nxge_rxdma_regs_dump_channels(nxgep);
+ miocack(wq, mp, 0, 0);
+ break;
+ case NXGE_VIR_INT_REGS_DUMP:
+ case NXGE_INT_REGS_DUMP:
+ nxge_virint_regs_dump(nxgep);
+ miocack(wq, mp, 0, 0);
+ break;
+ case NXGE_RTRACE:
+ nxge_rtrace_ioctl(nxgep, wq, mp, iocp);
+ break;
+ }
+}
+
+void
+nxge_loopback_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp,
+ struct iocblk *iocp)
+{
+ p_lb_property_t lb_props;
+ size_t size;
+ int i;
+
+ if (mp->b_cont == NULL) {
+ miocnak(wq, mp, 0, EINVAL);
+ }
+ switch (iocp->ioc_cmd) {
+ case LB_GET_MODE:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_MODE command"));
+ if (nxgep != NULL) {
+ *(lb_info_sz_t *)mp->b_cont->b_rptr =
+ nxgep->statsp->port_stats.lb_mode;
+ miocack(wq, mp, sizeof (nxge_lb_t), 0);
+ } else
+ miocnak(wq, mp, 0, EINVAL);
+ break;
+ case LB_SET_MODE:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_SET_LB_MODE command"));
+ if (iocp->ioc_count != sizeof (uint32_t)) {
+ miocack(wq, mp, 0, 0);
+ break;
+ }
+ if ((nxgep != NULL) && nxge_set_lb(nxgep, wq, mp->b_cont)) {
+ miocack(wq, mp, 0, 0);
+ } else {
+ miocnak(wq, mp, 0, EPROTO);
+ }
+ break;
+ case LB_GET_INFO_SIZE:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "LB_GET_INFO_SIZE command"));
+ if (nxgep != NULL) {
+ size = sizeof (lb_normal);
+ if (nxgep->statsp->mac_stats.cap_10gfdx) {
+ size += sizeof (lb_external10g);
+ size += sizeof (lb_phy10g);
+ size += sizeof (lb_serdes10g);
+ size += sizeof (lb_mac10g);
+ }
+ if (nxgep->statsp->mac_stats.cap_1000fdx) {
+ size += sizeof (lb_external1000);
+ size += sizeof (lb_mac1000);
+ if (nxgep->mac.portmode == PORT_1G_COPPER)
+ size += sizeof (lb_phy1000);
+ }
+ if (nxgep->statsp->mac_stats.cap_100fdx)
+ size += sizeof (lb_external100);
+ if (nxgep->statsp->mac_stats.cap_10fdx)
+ size += sizeof (lb_external10);
+ else if (nxgep->mac.portmode == PORT_1G_FIBER)
+ size += sizeof (lb_serdes1000);
+ *(lb_info_sz_t *)mp->b_cont->b_rptr = size;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "NXGE_GET_LB_INFO command: size %d", size));
+
+ miocack(wq, mp, sizeof (lb_info_sz_t), 0);
+ } else
+ miocnak(wq, mp, 0, EINVAL);
+ break;
+
+ case LB_GET_INFO:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_INFO command"));
+ if (nxgep != NULL) {
+ size = sizeof (lb_normal);
+ if (nxgep->statsp->mac_stats.cap_10gfdx) {
+ size += sizeof (lb_external10g);
+ size += sizeof (lb_phy10g);
+ size += sizeof (lb_serdes10g);
+ size += sizeof (lb_mac10g);
+ }
+ if (nxgep->statsp->mac_stats.cap_1000fdx) {
+ size += sizeof (lb_external1000);
+ size += sizeof (lb_mac1000);
+ if (nxgep->mac.portmode == PORT_1G_COPPER)
+ size += sizeof (lb_phy1000);
+ }
+ if (nxgep->statsp->mac_stats.cap_100fdx)
+ size += sizeof (lb_external100);
+ if (nxgep->statsp->mac_stats.cap_10fdx)
+ size += sizeof (lb_external10);
+ else if (nxgep->mac.portmode == PORT_1G_FIBER)
+ size += sizeof (lb_serdes1000);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "NXGE_GET_LB_INFO command: size %d", size));
+
+ if (size == iocp->ioc_count) {
+ i = 0;
+ lb_props = (p_lb_property_t)mp->b_cont->b_rptr;
+ lb_props[i++] = lb_normal;
+ if (nxgep->statsp->mac_stats.cap_10gfdx) {
+ lb_props[i++] = lb_mac10g;
+ lb_props[i++] = lb_serdes10g;
+ lb_props[i++] = lb_phy10g;
+ lb_props[i++] = lb_external10g;
+ }
+ if (nxgep->statsp->mac_stats.cap_1000fdx)
+ lb_props[i++] = lb_external1000;
+ if (nxgep->statsp->mac_stats.cap_100fdx)
+ lb_props[i++] = lb_external100;
+ if (nxgep->statsp->mac_stats.cap_10fdx)
+ lb_props[i++] = lb_external10;
+ if (nxgep->statsp->mac_stats.cap_1000fdx)
+ lb_props[i++] = lb_mac1000;
+ if (nxgep->mac.portmode == PORT_1G_COPPER) {
+ if (nxgep->statsp->mac_stats.
+ cap_1000fdx)
+ lb_props[i++] = lb_phy1000;
+ } else if (nxgep->mac.portmode ==
+ PORT_1G_FIBER)
+ lb_props[i++] = lb_serdes1000;
+ miocack(wq, mp, size, 0);
+ } else
+ miocnak(wq, mp, 0, EINVAL);
+ } else {
+ miocnak(wq, mp, 0, EINVAL);
+ cmn_err(CE_NOTE, "!nxge_hw_ioctl: invalid command 0x%x",
+ iocp->ioc_cmd);
+ }
+
+ break;
+ }
+}
+
+/*
+ * DMA channel interfaces to access various channel specific
+ * hardware functions.
+ */
+void
+nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle, void *reg_addrp,
+ uint32_t reg_base,
+ uint16_t channel, uint64_t reg_data)
+{
+ uint64_t reg_offset;
+
+ NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
+
+ /*
+ * Channel is assumed to be from 0 to
+ * the maximum DMA channel #.
+ * If we use the virtual DMA CSR address space
+ * from the config space (in PCI case), then the
+ * following code need to be use different offset
+ * computation macro.
+ */
+ reg_offset = reg_base + DMC_OFFSET(channel);
+ NXGE_PIO_WRITE64(handle, reg_addrp, reg_offset, reg_data);
+
+ NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
+}
+
+uint64_t
+nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle, void *reg_addrp,
+ uint32_t reg_base,
+ uint16_t channel)
+{
+ uint64_t reg_offset;
+
+ NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
+
+ /*
+ * Channel is assumed to be from 0 to
+ * the maximum DMA channel #.
+ * If we use the virtual DMA CSR address space
+ * from the config space (in PCI case), then the
+ * following code need to be use different offset
+ * computation macro.
+ */
+ reg_offset = reg_base + DMC_OFFSET(channel);
+
+ NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
+
+ return (NXGE_PIO_READ64(handle, reg_addrp, reg_offset));
+}
+
+void
+nxge_get32(p_nxge_t nxgep, p_mblk_t mp)
+{
+ nxge_os_acc_handle_t nxge_regh;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
+ nxge_regh = nxgep->dev_regs->nxge_regh;
+
+ *(uint32_t *)mp->b_rptr = NXGE_PIO_READ32(nxge_regh,
+ nxgep->dev_regs->nxge_regp, *(uint32_t *)mp->b_rptr);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "value = 0x%08X",
+ *(uint32_t *)mp->b_rptr));
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
+}
+
+void
+nxge_put32(p_nxge_t nxgep, p_mblk_t mp)
+{
+ nxge_os_acc_handle_t nxge_regh;
+ uint32_t *buf;
+ uint8_t *reg;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
+ nxge_regh = nxgep->dev_regs->nxge_regh;
+
+ buf = (uint32_t *)mp->b_rptr;
+ reg = (uint8_t *)(nxgep->dev_regs->nxge_regp) + buf[0];
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "reg = 0x%016llX index = 0x%08X value = 0x%08X",
+ reg, buf[0], buf[1]));
+ NXGE_PIO_WRITE32(nxge_regh, (uint32_t *)reg, 0, buf[1]);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
+}
+
+/*ARGSUSED*/
+boolean_t
+nxge_set_lb(p_nxge_t nxgep, queue_t *wq, p_mblk_t mp)
+{
+ boolean_t status = B_TRUE;
+ uint32_t lb_mode;
+ lb_property_t *lb_info;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_set_lb"));
+ lb_mode = nxgep->statsp->port_stats.lb_mode;
+ if (lb_mode == *(uint32_t *)mp->b_rptr) {
+ cmn_err(CE_NOTE,
+ "!nxge%d: Loopback mode already set (lb_mode %d).\n",
+ nxgep->instance, lb_mode);
+ status = B_FALSE;
+ goto nxge_set_lb_exit;
+ }
+
+ lb_mode = *(uint32_t *)mp->b_rptr;
+ lb_info = NULL;
+ if (lb_mode == lb_normal.value)
+ lb_info = &lb_normal;
+ else if ((lb_mode == lb_external10g.value) &&
+ (nxgep->statsp->mac_stats.cap_10gfdx))
+ lb_info = &lb_external10g;
+ else if ((lb_mode == lb_external1000.value) &&
+ (nxgep->statsp->mac_stats.cap_1000fdx))
+ lb_info = &lb_external1000;
+ else if ((lb_mode == lb_external100.value) &&
+ (nxgep->statsp->mac_stats.cap_100fdx))
+ lb_info = &lb_external100;
+ else if ((lb_mode == lb_external10.value) &&
+ (nxgep->statsp->mac_stats.cap_10fdx))
+ lb_info = &lb_external10;
+ else if ((lb_mode == lb_phy10g.value) &&
+ ((nxgep->mac.portmode == PORT_10G_COPPER) ||
+ (nxgep->mac.portmode == PORT_10G_FIBER)))
+ lb_info = &lb_phy10g;
+ else if ((lb_mode == lb_phy1000.value) &&
+ (nxgep->mac.portmode == PORT_1G_COPPER))
+ lb_info = &lb_phy1000;
+ else if ((lb_mode == lb_phy.value) &&
+ (nxgep->mac.portmode == PORT_1G_COPPER))
+ lb_info = &lb_phy;
+ else if ((lb_mode == lb_serdes10g.value) &&
+ (nxgep->mac.portmode == PORT_10G_FIBER) ||
+ (nxgep->mac.portmode == PORT_10G_COPPER))
+ lb_info = &lb_serdes10g;
+ else if ((lb_mode == lb_serdes1000.value) &&
+ (nxgep->mac.portmode == PORT_1G_FIBER))
+ lb_info = &lb_serdes1000;
+ else if (lb_mode == lb_mac10g.value)
+ lb_info = &lb_mac10g;
+ else if (lb_mode == lb_mac1000.value)
+ lb_info = &lb_mac1000;
+ else if (lb_mode == lb_mac.value)
+ lb_info = &lb_mac;
+ else {
+ cmn_err(CE_NOTE,
+ "!nxge%d: Loopback mode not supported(mode %d).\n",
+ nxgep->instance, lb_mode);
+ status = B_FALSE;
+ goto nxge_set_lb_exit;
+ }
+
+ if (lb_mode == nxge_lb_normal) {
+ if (nxge_lb_dbg) {
+ cmn_err(CE_NOTE,
+ "!nxge%d: Returning to normal operation",
+ nxgep->instance);
+ }
+ nxge_set_lb_normal(nxgep);
+ goto nxge_set_lb_exit;
+ }
+
+ nxgep->statsp->port_stats.lb_mode = lb_mode;
+
+ if (nxge_lb_dbg)
+ cmn_err(CE_NOTE,
+ "!nxge%d: Adapter now in %s loopback mode",
+ nxgep->instance, lb_info->key);
+ nxgep->param_arr[param_autoneg].value = 0;
+ nxgep->param_arr[param_anar_10gfdx].value =
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g);
+ nxgep->param_arr[param_anar_10ghdx].value = 0;
+ nxgep->param_arr[param_anar_1000fdx].value =
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000);
+ nxgep->param_arr[param_anar_1000hdx].value = 0;
+ nxgep->param_arr[param_anar_100fdx].value =
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100);
+ nxgep->param_arr[param_anar_100hdx].value = 0;
+ nxgep->param_arr[param_anar_10fdx].value =
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10);
+ if (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) {
+ nxgep->param_arr[param_master_cfg_enable].value = 1;
+ nxgep->param_arr[param_master_cfg_value].value = 1;
+ }
+ if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy)) {
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_xcvr_find(nxgep);
+ (void) nxge_link_init(nxgep);
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+ }
+
+ if (lb_info->lb_type == internal) {
+ if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g))
+ nxgep->statsp->mac_stats.link_speed = 10000;
+ else if ((nxgep->statsp->port_stats.lb_mode
+ == nxge_lb_mac1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
+ (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000)) {
+ nxgep->statsp->mac_stats.link_speed = 1000;
+ } else {
+ nxgep->statsp->mac_stats.link_speed = 100;
+ }
+ nxgep->statsp->mac_stats.link_duplex = 2;
+ nxgep->statsp->mac_stats.link_up = 1;
+ }
+
+ nxge_global_reset(nxgep);
+
+nxge_set_lb_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_set_lb status = 0x%08x", status));
+ return (status);
+}
+
+void
+nxge_set_lb_normal(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_lb_normal"));
+ nxgep->statsp->port_stats.lb_mode = nxge_lb_normal;
+ nxgep->param_arr[param_autoneg].value =
+ nxgep->param_arr[param_autoneg].old_value;
+ nxgep->param_arr[param_anar_1000fdx].value =
+ nxgep->param_arr[param_anar_1000fdx].old_value;
+ nxgep->param_arr[param_anar_1000hdx].value =
+ nxgep->param_arr[param_anar_1000hdx].old_value;
+ nxgep->param_arr[param_anar_100fdx].value =
+ nxgep->param_arr[param_anar_100fdx].old_value;
+ nxgep->param_arr[param_anar_100hdx].value =
+ nxgep->param_arr[param_anar_100hdx].old_value;
+ nxgep->param_arr[param_anar_10fdx].value =
+ nxgep->param_arr[param_anar_10fdx].old_value;
+ nxgep->param_arr[param_master_cfg_enable].value =
+ nxgep->param_arr[param_master_cfg_enable].old_value;
+ nxgep->param_arr[param_master_cfg_value].value =
+ nxgep->param_arr[param_master_cfg_value].old_value;
+
+ nxge_global_reset(nxgep);
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_xcvr_find(nxgep);
+ (void) nxge_link_init(nxgep);
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_lb_normal"));
+}
+
+void
+nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp)
+{
+ uint16_t reg;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_get_mii"));
+
+ reg = *(uint16_t *)mp->b_rptr;
+ (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, reg,
+ (uint16_t *)mp->b_rptr);
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "reg = 0x%08X value = 0x%04X",
+ reg, *(uint16_t *)mp->b_rptr));
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_get_mii"));
+}
+
+void
+nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp)
+{
+ uint16_t *buf;
+ uint8_t reg;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_put_mii"));
+ buf = (uint16_t *)mp->b_rptr;
+ reg = (uint8_t)buf[0];
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "reg = 0x%08X index = 0x%08X value = 0x%08X",
+ reg, buf[0], buf[1]));
+
+ (void) nxge_mii_write(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
+ reg, buf[1]);
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_put_mii"));
+}
+
+void
+nxge_check_hw_state(p_nxge_t nxgep)
+{
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldv_t t_ldvp;
+
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "==> nxge_check_hw_state"));
+
+ nxge_check_tx_hang(nxgep);
+
+ ldgvp = nxgep->ldgvp;
+ if (ldgvp == NULL || (ldgvp->ldvp_syserr == NULL)) {
+ NXGE_ERROR_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
+ "NULL ldgvp (interrupt not ready)."));
+ return;
+ }
+ t_ldvp = ldgvp->ldvp_syserr;
+ if (!t_ldvp->use_timer) {
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
+ "ldgvp $%p t_ldvp $%p use_timer flag %d",
+ ldgvp, t_ldvp, t_ldvp->use_timer));
+ return;
+ }
+
+ (void) nxge_syserr_intr((void *)t_ldvp, (void *)nxgep);
+
+ nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state,
+ NXGE_CHECK_TIMER);
+
+ NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_rtrace_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
+{
+ ssize_t size;
+ rtrace_t *rtp;
+ mblk_t *nmp;
+ uint32_t i, j;
+ uint32_t start_blk;
+ uint32_t base_entry;
+ uint32_t num_entries;
+
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_rtrace_ioctl"));
+
+ size = 1024;
+ if (mp->b_cont == NULL || MBLKL(mp->b_cont) < size) {
+ NXGE_DEBUG_MSG((nxgep, STR_CTL,
+ "malformed M_IOCTL MBLKL = %d size = %d",
+ MBLKL(mp->b_cont), size));
+ miocnak(wq, mp, 0, EINVAL);
+ return;
+ }
+
+ nmp = mp->b_cont;
+ rtp = (rtrace_t *)nmp->b_rptr;
+ start_blk = rtp->next_idx;
+ num_entries = rtp->last_idx;
+ base_entry = start_blk * MAX_RTRACE_IOC_ENTRIES;
+
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "start_blk = %d\n", start_blk));
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "num_entries = %d\n", num_entries));
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "base_entry = %d\n", base_entry));
+
+ rtp->next_idx = npi_rtracebuf.next_idx;
+ rtp->last_idx = npi_rtracebuf.last_idx;
+ rtp->wrapped = npi_rtracebuf.wrapped;
+ for (i = 0, j = base_entry; i < num_entries; i++, j++) {
+ rtp->buf[i].ctl_addr = npi_rtracebuf.buf[j].ctl_addr;
+ rtp->buf[i].val_l32 = npi_rtracebuf.buf[j].val_l32;
+ rtp->buf[i].val_h32 = npi_rtracebuf.buf[j].val_h32;
+ }
+
+ nmp->b_wptr = nmp->b_rptr + size;
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_rtrace_ioctl"));
+
+ miocack(wq, mp, (int)size, 0);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_ipp.c b/usr/src/uts/sun4v/io/nxge/nxge_ipp.c
new file mode 100644
index 0000000000..ac6be18130
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_ipp.c
@@ -0,0 +1,606 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nxge_impl.h>
+#include <nxge_ipp.h>
+
+nxge_status_t
+nxge_ipp_init(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ uint32_t config;
+ npi_handle_t handle;
+ uint32_t pkt_size;
+ ipp_status_t istatus;
+ npi_status_t rs = NPI_SUCCESS;
+ uint64_t val;
+ uint32_t d0, d1, d2, d3, d4;
+ int i;
+ uint32_t dfifo_entries;
+
+ handle = nxgep->npi_handle;
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn));
+
+ /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */
+
+ if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) {
+ if (portn < 2)
+ dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
+ else
+ dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
+ } else if (nxgep->niu_type == N2_NIU) {
+ dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
+ } else
+ goto fail;
+
+ for (i = 0; i < dfifo_entries; i++) {
+ if ((rs = npi_ipp_write_dfifo(handle, portn, i, 0, 0, 0, 0, 0))
+ != NPI_SUCCESS)
+ goto fail;
+ if ((rs = npi_ipp_read_dfifo(handle, portn, i, &d0, &d1, &d2,
+ &d3, &d4)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ /* Clear PFIFO DFIFO status bits */
+
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ goto fail;
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ goto fail;
+
+ /*
+ * Soft reset to make sure we bring the FIFO pointers back to the
+ * original initial position.
+ */
+ if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ /* Clean up ECC counter */
+ IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val);
+ IPP_REG_RD(nxgep->npi_handle, portn, IPP_TCP_CKSUM_ERR_CNT_REG, &val);
+ IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val);
+
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ goto fail;
+
+ /* Configure IPP port */
+ if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL))
+ != NPI_SUCCESS)
+ goto fail;
+ nxgep->ipp.iconfig = ICFG_IPP_ALL;
+
+ config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
+ CFG_IPP_TCP_UDP_CKSUM;
+ if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->ipp.config = config;
+
+ /* Set max packet size */
+ pkt_size = IPP_MAX_PKT_SIZE;
+ if ((rs = npi_ipp_set_max_pktsize(handle, portn, IPP_MAX_PKT_SIZE)) !=
+ NPI_SUCCESS)
+ goto fail;
+ nxgep->ipp.max_pkt_size = pkt_size;
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_init: Fail to initialize IPP Port #%d\n",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+
+nxge_status_t
+nxge_ipp_disable(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ uint32_t config;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn));
+
+ /* disable the IPP */
+ config = nxgep->ipp.config;
+ if ((rs = npi_ipp_config(handle, DISABLE, portn, config))
+ != NPI_SUCCESS) {
+ goto fail;
+ }
+
+/* add code to reset control FIFO */
+ /* IPP soft reset */
+ if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_disable: Fail to disable IPP Port #%d\n",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+nxge_status_t
+nxge_ipp_reset(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ uint32_t config;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ uint16_t wr_ptr, rd_ptr;
+ uint32_t try_count;
+ handle = nxgep->npi_handle;
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn));
+
+ /* disable the IPP */
+ config = nxgep->ipp.config;
+ if ((rs = npi_ipp_config(handle, DISABLE, portn, config))
+ != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /*
+ * Wait until ip read and write fifo pointers
+ * are equal
+ */
+ (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
+ (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
+ try_count = 10;
+
+ while ((try_count > 0) && (rd_ptr != wr_ptr)) {
+ (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
+ (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
+ try_count--;
+ }
+
+ if (try_count == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_ipp_reset: port%d failed"
+ " rd_fifo != wr_fifo", portn));
+ goto fail;
+ }
+
+ /* IPP soft reset */
+ if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* to reset control FIFO */
+ if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /*
+ * Making sure that error source is cleared if this is an
+ * injected error.
+ */
+ IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_init: Fail to Reset IPP Port #%d\n",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+
+
+nxge_status_t
+nxge_ipp_enable(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ uint32_t config;
+ npi_handle_t handle;
+ uint32_t pkt_size;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn));
+
+ config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
+ CFG_IPP_TCP_UDP_CKSUM;
+ if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->ipp.config = config;
+
+ /* Set max packet size */
+ pkt_size = IPP_MAX_PKT_SIZE;
+ if ((rs = npi_ipp_set_max_pktsize(handle, portn, IPP_MAX_PKT_SIZE)) !=
+ NPI_SUCCESS)
+ goto fail;
+ nxgep->ipp.max_pkt_size = pkt_size;
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_init: Fail to Enable IPP Port #%d\n",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+
+nxge_status_t
+nxge_ipp_handle_sys_errors(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_ipp_stats_t statsp;
+ ipp_status_t istatus;
+ uint8_t portn;
+ p_ipp_errlog_t errlogp;
+ boolean_t rxport_fatal = B_FALSE;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+ statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats;
+ portn = nxgep->mac.portnum;
+
+ errlogp = (p_ipp_errlog_t)&statsp->errlog;
+
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+ if (istatus.value == 0)
+ /*
+ * The error is not initiated from this port, so just exit.
+ */
+ return (NXGE_OK);
+
+ if (istatus.bits.w0.dfifo_missed_sop) {
+ statsp->sop_miss++;
+ if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
+ &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ if ((rs = npi_ipp_get_state_mach(handle, portn,
+ &errlogp->state_mach)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_SOP_MISS);
+ if (statsp->sop_miss < IPP_MAX_ERR_SHOW)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: sop_miss\n"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus.bits.w0.dfifo_missed_eop) {
+ statsp->eop_miss++;
+ if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
+ &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ if ((rs = npi_ipp_get_state_mach(handle, portn,
+ &errlogp->state_mach)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_EOP_MISS);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: eop_miss\n"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus.bits.w0.dfifo_uncorr_ecc_err) {
+ statsp->dfifo_ue++;
+ if ((rs = npi_ipp_get_ecc_syndrome(handle, portn,
+ &errlogp->ecc_syndrome)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_DFIFO_UE);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: dfifo_ue\n"));
+ rxport_fatal = B_TRUE;
+ }
+#ifdef IPP_ECC_CORR_ERR
+ if (istatus.bits.w0.dfifo_corr_ecc_err) {
+ /*
+ * Do nothing here. ECC errors are collected from the
+ * ECC counter.
+ */
+ ;
+ }
+#endif
+ if (istatus.bits.w0.pre_fifo_perr) {
+ statsp->pfifo_perr++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_PFIFO_PERR);
+ if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: pre_pifo_perr\n"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus.bits.w0.ecc_err_cnt_ovfl) {
+ statsp->ecc_err_cnt += IPP_ECC_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_ECC_ERR_MAX);
+ if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW * IPP_ECC_CNT_MASK))
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: ecc_err_max\n"));
+ }
+ if (istatus.bits.w0.pre_fifo_overrun) {
+ statsp->pfifo_over++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_PFIFO_OVER);
+ if (statsp->pfifo_over < IPP_MAX_ERR_SHOW)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: pfifo_over\n"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus.bits.w0.pre_fifo_underrun) {
+ statsp->pfifo_und++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_PFIFO_UND);
+ if (statsp->pfifo_und < IPP_MAX_ERR_SHOW)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: fatal error: pfifo_und\n"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus.bits.w0.bad_cksum_cnt_ovfl) {
+ statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_BAD_CS_MX);
+ if (statsp->bad_cs_cnt <
+ (IPP_MAX_ERR_SHOW * IPP_BAD_CS_CNT_MASK))
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: bad_cs_max\n"));
+ }
+ if (istatus.bits.w0.pkt_discard_cnt_ovfl) {
+ statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_IPP_PKT_DIS_MX);
+ if (statsp->pkt_dis_cnt <
+ (IPP_MAX_ERR_SHOW * IPP_PKT_DIS_CNT_MASK))
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ipp_err_evnts: pkt_dis_max\n"));
+ }
+
+ /*
+ * Making sure that error source is cleared if this is an
+ * injected error.
+ */
+ IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
+
+ if (rxport_fatal) {
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL,
+ " nxge_ipp_handle_sys_errors:"
+ " fatal Error on Port #%d\n",
+ portn));
+ status = nxge_ipp_fatal_err_recover(nxgep);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ return (status);
+}
+
+void
+nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id)
+{
+ ipp_status_t ipps;
+ ipp_ecc_ctrl_t ecc_ctrl;
+ uint8_t portn = nxgep->mac.portnum;
+
+ switch (err_id) {
+ case NXGE_FM_EREPORT_IPP_DFIFO_UE:
+ ecc_ctrl.value = 0;
+ ecc_ctrl.bits.w0.cor_dbl = 1;
+ ecc_ctrl.bits.w0.cor_1 = 1;
+ ecc_ctrl.bits.w0.cor_lst = 1;
+ cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
+ (unsigned long long)ecc_ctrl.value);
+ IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
+ ecc_ctrl.value);
+ break;
+ case NXGE_FM_EREPORT_IPP_DFIFO_CE:
+ ecc_ctrl.value = 0;
+ ecc_ctrl.bits.w0.cor_sng = 1;
+ ecc_ctrl.bits.w0.cor_1 = 1;
+ ecc_ctrl.bits.w0.cor_snd = 1;
+ cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
+ (unsigned long long)ecc_ctrl.value);
+ IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
+ ecc_ctrl.value);
+ break;
+ case NXGE_FM_EREPORT_IPP_EOP_MISS:
+ case NXGE_FM_EREPORT_IPP_SOP_MISS:
+ case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
+ case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
+ case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
+ case NXGE_FM_EREPORT_IPP_PFIFO_UND:
+ case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
+ case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
+ case NXGE_FM_EREPORT_IPP_RESET_FAIL:
+ IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
+ &ipps.value);
+ if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS)
+ ipps.bits.w0.dfifo_missed_eop = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS)
+ ipps.bits.w0.dfifo_missed_sop = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE)
+ ipps.bits.w0.dfifo_uncorr_ecc_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE)
+ ipps.bits.w0.dfifo_corr_ecc_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR)
+ ipps.bits.w0.pre_fifo_perr = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX)
+ ipps.bits.w0.ecc_err_cnt_ovfl = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER)
+ ipps.bits.w0.pre_fifo_overrun = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND)
+ ipps.bits.w0.pre_fifo_underrun = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX)
+ ipps.bits.w0.bad_cksum_cnt_ovfl = 1;
+ else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX)
+ ipps.bits.w0.pkt_discard_cnt_ovfl = 1;
+ cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n",
+ (unsigned long long)ipps.value);
+ IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
+ ipps.value);
+ break;
+ }
+}
+
+nxge_status_t
+nxge_ipp_fatal_err_recover(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ uint8_t portn;
+ uint16_t wr_ptr;
+ uint16_t rd_ptr;
+ uint32_t try_count;
+ uint32_t dfifo_entries;
+ ipp_status_t istatus;
+ uint32_t d0, d1, d2, d3, d4;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover"));
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from RxPort error..."));
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ /*
+ * Making sure that error source is cleared if this is an
+ * injected error.
+ */
+ IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
+
+ /* Disable RxMAC */
+
+ if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
+ goto fail;
+
+ /* When recovering from IPP, RxDMA channel resets are not necessary */
+ /* Reset ZCP CFIFO */
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn));
+ if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ /*
+ * Wait until ip read and write fifo pointers
+ * are equal
+ */
+ (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
+ (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
+ try_count = 512;
+
+ while ((try_count > 0) && (rd_ptr != wr_ptr)) {
+ (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
+ (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
+ try_count--;
+ }
+
+ if (try_count == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_ipp_reset: port%d IPP stalled..."
+ " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x",
+ portn, rd_ptr, wr_ptr));
+ /*
+ * This means the fatal error occurred on the first line
+ * of the fifo. In this case, just reset the IPP without
+ * draining the PFIFO.
+ */
+ }
+
+ if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) {
+ if (portn < 2)
+ dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
+ else
+ dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
+ } else if (nxgep->niu_type == N2_NIU) {
+ dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
+ } else
+ goto fail;
+
+ /* Clean up DFIFO SRAM entries */
+ for (i = 0; i < dfifo_entries; i++) {
+ if ((rs = npi_ipp_write_dfifo(handle, portn, i, 0, 0, 0, 0, 0))
+ != NPI_SUCCESS)
+ goto fail;
+ if ((rs = npi_ipp_read_dfifo(handle, portn, i, &d0, &d1, &d2,
+ &d3, &d4)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ /* Clear PFIFO DFIFO status bits */
+
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ goto fail;
+ if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
+ goto fail;
+
+ /* Reset IPP */
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn));
+ if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn));
+ if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn));
+
+ if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn));
+
+ if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
+ goto fail;
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Sucessful, RxPort Restored"));
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover"));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+ return (status | rs);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_kstats.c b/usr/src/uts/sun4v/io/nxge/nxge_kstats.c
new file mode 100644
index 0000000000..4a993bde3c
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_kstats.c
@@ -0,0 +1,2781 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <inet/mi.h>
+#define RDC_NAME_FORMAT1 "RDC Channel"
+#define TDC_NAME_FORMAT1 "TDC Channel"
+#define CH_NAME_FORMAT " %d Stats"
+#define TDC_NAME_FORMAT "TDC Channel %d Stats"
+#define RDC_NAME_FORMAT "RDC Channel %d Stats"
+
+void nxge_mac_init_kstats(p_nxge_t, struct kstat *);
+void nxge_xmac_init_kstats(struct kstat *);
+void nxge_bmac_init_kstats(struct kstat *);
+
+
+void
+nxge_init_statsp(p_nxge_t nxgep)
+{
+
+ size_t stats_size;
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_init_statsp"));
+
+ stats_size = sizeof (nxge_stats_t);
+ nxgep->statsp = KMEM_ZALLOC(stats_size, KM_SLEEP);
+ nxgep->statsp->stats_size = stats_size;
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, " <== nxge_init_statsp"));
+
+}
+
+typedef struct {
+ uint8_t index;
+ uint8_t type;
+ char *name;
+} nxge_kstat_index_t;
+
+typedef enum {
+ RDC_STAT_PACKETS = 0,
+ RDC_STAT_BYTES,
+ RDC_STAT_ERRORS,
+ RDC_STAT_DCF_ERR,
+ RDC_STAT_RCR_ACK_ERR,
+ RDC_STAT_RCR_DC_FIFOFLOW_ERR,
+ RDC_STAT_RCR_SHA_PAR_ERR,
+ RDC_STAT_RBR_PRE_PAR_ERR,
+ RDC_STAT_WRED_DROP,
+ RDC_STAT_RBR_PRE_EMTY,
+ RDC_STAT_RCR_SHADOW_FULL,
+ RDC_STAT_RBR_TMOUT,
+ RDC_STAT_RSP_CNT_ERR,
+ RDC_STAT_BYTE_EN_BUS,
+ RDC_STAT_RSP_DAT_ERR,
+ RDC_STAT_COMPL_L2_ERR,
+ RDC_STAT_COMPL_L4_CKSUM_ERR,
+ RDC_STAT_COMPL_ZCP_SOFT_ERR,
+ RDC_STAT_COMPL_FFLP_SOFT_ERR,
+ RDC_STAT_CONFIG_ERR,
+ RDC_STAT_RCRINCON,
+ RDC_STAT_RCRFULL,
+ RDC_STAT_RBR_EMPTY,
+ RDC_STAT_RBR_FULL,
+ RDC_STAT_RBRLOGPAGE,
+ RDC_STAT_CFIGLOGPAGE,
+ RDC_STAT_PORT_DROP_PKT,
+ RDC_STAT_RCRTO,
+ RDC_STAT_RCRTHRES,
+ RDC_STAT_MEX,
+ RDC_STAT_ID_MIS,
+ RDC_STAT_ZCP_EOP,
+ RDC_STAT_IPP_EOP,
+ RDC_STAT_END
+} nxge_rdc_stat_index_t;
+
+nxge_kstat_index_t nxge_rdc_stats[] = {
+ {RDC_STAT_PACKETS, KSTAT_DATA_UINT64, "rdc_packets"},
+ {RDC_STAT_BYTES, KSTAT_DATA_UINT64, "rdc_bytes"},
+ {RDC_STAT_ERRORS, KSTAT_DATA_ULONG, "rdc_errors"},
+ {RDC_STAT_DCF_ERR, KSTAT_DATA_ULONG, "rdc_dcf_err"},
+ {RDC_STAT_RCR_ACK_ERR, KSTAT_DATA_ULONG, "rdc_rcr_ack_err"},
+
+ {RDC_STAT_RCR_DC_FIFOFLOW_ERR,
+ KSTAT_DATA_ULONG, "rdc_dc_fifoflow_err"},
+ {RDC_STAT_RCR_SHA_PAR_ERR,
+ KSTAT_DATA_ULONG, "rdc_rcr_sha_par_err"},
+ {RDC_STAT_RBR_PRE_PAR_ERR,
+ KSTAT_DATA_ULONG, "rdc_rbr_pre_par_err"},
+ {RDC_STAT_WRED_DROP, KSTAT_DATA_ULONG, "rdc_wred_drop"},
+ {RDC_STAT_RBR_PRE_EMTY, KSTAT_DATA_ULONG, "rdc_rbr_pre_empty"},
+
+ {RDC_STAT_RCR_SHADOW_FULL,
+ KSTAT_DATA_ULONG, "rdc_rcr_shadow_full"},
+ {RDC_STAT_RBR_TMOUT, KSTAT_DATA_ULONG, "rdc_rbr_tmout"},
+ {RDC_STAT_RSP_CNT_ERR, KSTAT_DATA_ULONG, "rdc_rsp_cnt_err"},
+ {RDC_STAT_BYTE_EN_BUS, KSTAT_DATA_ULONG, "rdc_byte_en_bus"},
+ {RDC_STAT_RSP_DAT_ERR, KSTAT_DATA_ULONG, "rdc_rsp_dat_err"},
+
+ {RDC_STAT_COMPL_L2_ERR, KSTAT_DATA_ULONG, "rdc_compl_l2_err"},
+ {RDC_STAT_COMPL_L4_CKSUM_ERR,
+ KSTAT_DATA_ULONG, "rdc_compl_l4_cksum"},
+ {RDC_STAT_COMPL_ZCP_SOFT_ERR,
+ KSTAT_DATA_ULONG, "rdc_compl_zcp_soft_err"},
+ {RDC_STAT_COMPL_FFLP_SOFT_ERR,
+ KSTAT_DATA_ULONG, "rdc_compl_fflp_soft_err"},
+ {RDC_STAT_CONFIG_ERR, KSTAT_DATA_ULONG, "rdc_config_err"},
+
+ {RDC_STAT_RCRINCON, KSTAT_DATA_ULONG, "rdc_rcrincon"},
+ {RDC_STAT_RCRFULL, KSTAT_DATA_ULONG, "rdc_rcrfull"},
+ {RDC_STAT_RBR_EMPTY, KSTAT_DATA_ULONG, "rdc_rbr_empty"},
+ {RDC_STAT_RBR_FULL, KSTAT_DATA_ULONG, "rdc_rbrfull"},
+ {RDC_STAT_RBRLOGPAGE, KSTAT_DATA_ULONG, "rdc_rbrlogpage"},
+
+ {RDC_STAT_CFIGLOGPAGE, KSTAT_DATA_ULONG, "rdc_cfiglogpage"},
+ {RDC_STAT_PORT_DROP_PKT,
+ KSTAT_DATA_ULONG, "rdc_port_drop_pkt"},
+ {RDC_STAT_RCRTO, KSTAT_DATA_ULONG, "rdc_rcrto"},
+ {RDC_STAT_RCRTHRES, KSTAT_DATA_ULONG, "rdc_rcrthres"},
+ {RDC_STAT_MEX, KSTAT_DATA_ULONG, "rdc_mex"},
+ {RDC_STAT_ID_MIS, KSTAT_DATA_ULONG, "rdc_id_mismatch"},
+ {RDC_STAT_ZCP_EOP, KSTAT_DATA_ULONG, "rdc_zcp_eop"},
+ {RDC_STAT_IPP_EOP, KSTAT_DATA_ULONG, "rdc_ipp_eop"},
+ {RDC_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ RDC_SYS_STAT_PRE_PAR_ERR = 0,
+ RDC_SYS_STAT_SHA_PAR_ERR,
+ RDC_SYS_STAT_ID_MISMATCH,
+ RDC_SYS_STAT_IPP_EOP_ERR,
+ RDC_SYS_STAT_ZCP_EOP_ERR,
+ RDC_SYS_STAT_END
+} nxge_rdc_sys_stat_idx_t;
+
+nxge_kstat_index_t nxge_rdc_sys_stats[] = {
+ {RDC_SYS_STAT_PRE_PAR_ERR, KSTAT_DATA_UINT64, "rdc_pre_par_err"},
+ {RDC_SYS_STAT_SHA_PAR_ERR, KSTAT_DATA_UINT64, "rdc_sha_par_err"},
+ {RDC_SYS_STAT_ID_MISMATCH, KSTAT_DATA_UINT64, "rdc_stat_id_mismatch"},
+ {RDC_SYS_STAT_IPP_EOP_ERR, KSTAT_DATA_UINT64, "rdc_ipp_eop_err"},
+ {RDC_SYS_STAT_ZCP_EOP_ERR, KSTAT_DATA_UINT64, "rdc_zcp_eop_err"},
+ {RDC_SYS_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ TDC_STAT_PACKETS = 0,
+ TDC_STAT_BYTES,
+ TDC_STAT_ERRORS,
+ TDC_STAT_TX_INITS,
+ TDC_STAT_TX_NO_BUF,
+ TDC_STAT_MBOX_ERR,
+ TDC_STAT_PKT_SIZE_ERR,
+ TDC_STAT_TX_RING_OFLOW,
+ TDC_STAT_PREF_BUF_ECC_ERR,
+ TDC_STAT_NACK_PREF,
+ TDC_STAT_NACK_PKT_RD,
+ TDC_STAT_CONF_PART_ERR,
+ TDC_STAT_PKT_PRT_ERR,
+ TDC_STAT_RESET_FAIL,
+ TDC_STAT_TX_STARTS,
+ TDC_STAT_TX_NOCANPUT,
+ TDC_STAT_TX_MSGDUP_FAIL,
+ TDC_STAT_TX_ALLOCB_FAIL,
+ TDC_STAT_TX_NO_DESC,
+ TDC_STAT_TX_DMA_BIND_FAIL,
+ TDC_STAT_TX_UFLOW,
+ TDC_STAT_TX_HDR_PKTS,
+ TDC_STAT_TX_DDI_PKTS,
+ TDC_STAT_TX_DVMA_PKTS,
+ TDC_STAT_TX_MAX_PEND,
+ TDC_STAT_END
+} nxge_tdc_stats_index_t;
+
+nxge_kstat_index_t nxge_tdc_stats[] = {
+ {TDC_STAT_PACKETS, KSTAT_DATA_UINT64, "tdc_packets"},
+ {TDC_STAT_BYTES, KSTAT_DATA_UINT64, "tdc_bytes"},
+ {TDC_STAT_ERRORS, KSTAT_DATA_UINT64, "tdc_errors"},
+ {TDC_STAT_TX_INITS, KSTAT_DATA_ULONG, "tdc_tx_inits"},
+ {TDC_STAT_TX_NO_BUF, KSTAT_DATA_ULONG, "tdc_tx_no_buf"},
+ {TDC_STAT_MBOX_ERR, KSTAT_DATA_ULONG, "tdc_mbox_err"},
+ {TDC_STAT_PKT_SIZE_ERR, KSTAT_DATA_ULONG, "tdc_pkt_size_err"},
+ {TDC_STAT_TX_RING_OFLOW,
+ KSTAT_DATA_ULONG, "tdc_tx_ring_oflow"},
+ {TDC_STAT_PREF_BUF_ECC_ERR,
+ KSTAT_DATA_ULONG, "tdc_pref_buf_err_err"},
+ {TDC_STAT_NACK_PREF, KSTAT_DATA_ULONG, "tdc_nack_pref"},
+ {TDC_STAT_NACK_PKT_RD, KSTAT_DATA_ULONG, "tdc_nack_pkt_rd"},
+ {TDC_STAT_CONF_PART_ERR,
+ KSTAT_DATA_ULONG, "tdc_conf_part_err"},
+ {TDC_STAT_PKT_PRT_ERR, KSTAT_DATA_ULONG, "tdc_pkt_prt_err"},
+ {TDC_STAT_RESET_FAIL, KSTAT_DATA_ULONG, "tdc_reset_fail"},
+ {TDC_STAT_TX_STARTS, KSTAT_DATA_ULONG, "tdc_tx_starts"},
+ {TDC_STAT_TX_NOCANPUT, KSTAT_DATA_ULONG, "tdc_tx_nocanput"},
+ {TDC_STAT_TX_MSGDUP_FAIL, KSTAT_DATA_ULONG, "tdc_tx_msgdup_fail"},
+ {TDC_STAT_TX_ALLOCB_FAIL, KSTAT_DATA_ULONG, "tdc_tx_allocb_fail"},
+ {TDC_STAT_TX_NO_DESC, KSTAT_DATA_ULONG, "tdc_tx_no_desc"},
+ {TDC_STAT_TX_DMA_BIND_FAIL, KSTAT_DATA_ULONG, "tdc_tx_dma_bind_fail"},
+ {TDC_STAT_TX_UFLOW, KSTAT_DATA_ULONG, "tdc_tx_uflow"},
+ {TDC_STAT_TX_HDR_PKTS, KSTAT_DATA_ULONG, "tdc_tx_hdr_pkts"},
+ {TDC_STAT_TX_DDI_PKTS, KSTAT_DATA_ULONG, "tdc_tx_ddi_pkts"},
+ {TDC_STAT_TX_DVMA_PKTS, KSTAT_DATA_ULONG, "tdc_tx_dvma_pkts"},
+ {TDC_STAT_TX_MAX_PEND, KSTAT_DATA_ULONG, "tdc_tx_max_pend"},
+ {TDC_STAT_END, NULL, NULL}
+};
+
+/* IPP Statistics definitions */
+
+typedef enum {
+ IPP_STAT_EOP_MISS = 0,
+ IPP_STAT_SOP_MISS,
+ IPP_STAT_DFIFO_UE,
+ IPP_STAT_ECC_ERR,
+ IPP_STAT_PFIFO_OVER,
+ IPP_STAT_PFIFO_UND,
+ IPP_STAT_BAD_CS,
+ IPP_STAT_BAD_DIS,
+ IPP_STAT_CS_FAIL,
+ IPP_STAT_END
+} nxge_ipp_stat_index_t;
+
+nxge_kstat_index_t nxge_ipp_stats[] = {
+ {IPP_STAT_EOP_MISS, KSTAT_DATA_ULONG, "rxipp_eop_miss"},
+ {IPP_STAT_SOP_MISS, KSTAT_DATA_ULONG, "rxipp_sop_miss"},
+ {IPP_STAT_DFIFO_UE, KSTAT_DATA_ULONG, "rxipp_dfifo_ue"},
+ {IPP_STAT_ECC_ERR, KSTAT_DATA_ULONG, "rxipp_ecc_err"},
+ {IPP_STAT_PFIFO_OVER, KSTAT_DATA_ULONG, "rxipp_pfifo_over"},
+ {IPP_STAT_PFIFO_UND, KSTAT_DATA_ULONG, "rxipp_pfifo_und"},
+ {IPP_STAT_BAD_CS, KSTAT_DATA_ULONG, "rxipp_bad_cs"},
+ {IPP_STAT_BAD_DIS, KSTAT_DATA_ULONG, "rxipp_bad_dis"},
+ {IPP_STAT_CS_FAIL, KSTAT_DATA_ULONG, "rxipp_cs_fail"},
+ {IPP_STAT_END, NULL, NULL}
+};
+
+/* TXC Statistics definitions */
+
+typedef enum {
+ TXC_STAT_PKT_STUFFED = 0,
+ TXC_STAT_PKT_XMIT,
+ TXC_STAT_RO_CORRECT_ERR,
+ TXC_STAT_RO_UNCORRECT_ERR,
+ TXC_STAT_SF_CORRECT_ERR,
+ TXC_STAT_SF_UNCORRECT_ERR,
+ TXC_STAT_ADDRESS_FAILED,
+ TXC_STAT_DMA_FAILED,
+ TXC_STAT_LENGTH_FAILED,
+ TXC_STAT_PKT_ASSY_DEAD,
+ TXC_STAT_REORDER_ERR,
+ TXC_STAT_END
+} nxge_txc_stat_index_t;
+
+nxge_kstat_index_t nxge_txc_stats[] = {
+ {TXC_STAT_PKT_STUFFED, KSTAT_DATA_ULONG, "txc_pkt_stuffed"},
+ {TXC_STAT_PKT_XMIT, KSTAT_DATA_ULONG, "txc_pkt_xmit"},
+ {TXC_STAT_RO_CORRECT_ERR, KSTAT_DATA_ULONG, "txc_ro_correct_err"},
+ {TXC_STAT_RO_UNCORRECT_ERR, KSTAT_DATA_ULONG, "txc_ro_uncorrect_err"},
+ {TXC_STAT_SF_CORRECT_ERR, KSTAT_DATA_ULONG, "txc_sf_correct_err"},
+ {TXC_STAT_SF_UNCORRECT_ERR, KSTAT_DATA_ULONG, "txc_sf_uncorrect_err"},
+ {TXC_STAT_ADDRESS_FAILED, KSTAT_DATA_ULONG, "txc_address_failed"},
+ {TXC_STAT_DMA_FAILED, KSTAT_DATA_ULONG, "txc_dma_failed"},
+ {TXC_STAT_LENGTH_FAILED, KSTAT_DATA_ULONG, "txc_length_failed"},
+ {TXC_STAT_PKT_ASSY_DEAD, KSTAT_DATA_ULONG, "txc_pkt_assy_dead"},
+ {TXC_STAT_REORDER_ERR, KSTAT_DATA_ULONG, "txc_reorder_err"},
+ {TXC_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ XMAC_STAT_TX_FRAME_CNT = 0,
+ XMAC_STAT_TX_UNDERFLOW_ERR,
+ XMAC_STAT_TX_MAXPKTSIZE_ERR,
+ XMAC_STAT_TX_OVERFLOW_ERR,
+ XMAC_STAT_TX_FIFO_XFR_ERR,
+ XMAC_STAT_TX_BYTE_CNT,
+ XMAC_STAT_RX_FRAME_CNT,
+ XMAC_STAT_RX_UNDERFLOW_ERR,
+ XMAC_STAT_RX_OVERFLOW_ERR,
+ XMAC_STAT_RX_CRC_ERR_CNT,
+ XMAC_STAT_RX_LEN_ERR_CNT,
+ XMAC_STAT_RX_VIOL_ERR_CNT,
+ XMAC_STAT_RX_BYTE_CNT,
+ XMAC_STAT_RX_HIST1_CNT,
+ XMAC_STAT_RX_HIST2_CNT,
+ XMAC_STAT_RX_HIST3_CNT,
+ XMAC_STAT_RX_HIST4_CNT,
+ XMAC_STAT_RX_HIST5_CNT,
+ XMAC_STAT_RX_HIST6_CNT,
+ XMAC_STAT_RX_HIST7_CNT,
+ XMAC_STAT_RX_BROADCAST_CNT,
+ XMAC_STAT_RX_MULT_CNT,
+ XMAC_STAT_RX_FRAG_CNT,
+ XMAC_STAT_RX_FRAME_ALIGN_ERR_CNT,
+ XMAC_STAT_RX_LINKFAULT_ERR_CNT,
+ XMAC_STAT_RX_REMOTEFAULT_ERR,
+ XMAC_STAT_RX_LOCALFAULT_ERR,
+ XMAC_STAT_RX_PAUSE_CNT,
+ XMAC_STAT_TX_PAUSE_STATE,
+ XMAC_STAT_TX_NOPAUSE_STATE,
+ XMAC_STAT_XPCS_DESKEW_ERR_CNT,
+ XMAC_STAT_XPCS_SYMBOL_L0_ERR_CNT,
+ XMAC_STAT_XPCS_SYMBOL_L1_ERR_CNT,
+ XMAC_STAT_XPCS_SYMBOL_L2_ERR_CNT,
+ XMAC_STAT_XPCS_SYMBOL_L3_ERR_CNT,
+ XMAC_STAT_END
+} nxge_xmac_stat_index_t;
+
+nxge_kstat_index_t nxge_xmac_stats[] = {
+ {XMAC_STAT_TX_FRAME_CNT, KSTAT_DATA_ULONG, "txmac_frame_cnt"},
+ {XMAC_STAT_TX_UNDERFLOW_ERR, KSTAT_DATA_ULONG, "tmac_underflow_err"},
+ {XMAC_STAT_TX_MAXPKTSIZE_ERR, KSTAT_DATA_ULONG,
+ "txmac_maxpktsize_err"},
+ {XMAC_STAT_TX_OVERFLOW_ERR, KSTAT_DATA_ULONG, "txmac_overflow_err"},
+ {XMAC_STAT_TX_FIFO_XFR_ERR, KSTAT_DATA_ULONG, "txmac_fifo_xfr_err"},
+ {XMAC_STAT_TX_BYTE_CNT, KSTAT_DATA_ULONG, "txmac_byte_cnt"},
+ {XMAC_STAT_RX_FRAME_CNT, KSTAT_DATA_ULONG, "rxmac_frame_cnt"},
+ {XMAC_STAT_RX_UNDERFLOW_ERR, KSTAT_DATA_ULONG, "rxmac_underflow_err"},
+ {XMAC_STAT_RX_OVERFLOW_ERR, KSTAT_DATA_ULONG, "rxmac_overflow_err"},
+ {XMAC_STAT_RX_CRC_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_crc_err"},
+ {XMAC_STAT_RX_LEN_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_length_err"},
+ {XMAC_STAT_RX_VIOL_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_code_violations"},
+ {XMAC_STAT_RX_BYTE_CNT, KSTAT_DATA_ULONG, "rxmac_byte_cnt"},
+ {XMAC_STAT_RX_HIST1_CNT, KSTAT_DATA_ULONG, "rxmac_64_cnt"},
+ {XMAC_STAT_RX_HIST2_CNT, KSTAT_DATA_ULONG, "rxmac_65_127_cnt"},
+ {XMAC_STAT_RX_HIST3_CNT, KSTAT_DATA_ULONG, "rxmac_128_255_cnt"},
+ {XMAC_STAT_RX_HIST4_CNT, KSTAT_DATA_ULONG, "rxmac_256_511_cnt"},
+ {XMAC_STAT_RX_HIST5_CNT, KSTAT_DATA_ULONG, "rxmac_512_1023_cnt"},
+ {XMAC_STAT_RX_HIST6_CNT, KSTAT_DATA_ULONG, "rxmac_1024_1522_cnt"},
+ {XMAC_STAT_RX_HIST7_CNT, KSTAT_DATA_ULONG, "rxmac_jumbo_cnt"},
+ {XMAC_STAT_RX_BROADCAST_CNT, KSTAT_DATA_ULONG, "rxmac_broadcast_cnt"},
+ {XMAC_STAT_RX_MULT_CNT, KSTAT_DATA_ULONG, "rxmac_multicast_cnt"},
+ {XMAC_STAT_RX_FRAG_CNT, KSTAT_DATA_ULONG, "rxmac_fragment_cnt"},
+ {XMAC_STAT_RX_FRAME_ALIGN_ERR_CNT,
+ KSTAT_DATA_ULONG, "rxmac_alignment_err"},
+ {XMAC_STAT_RX_LINKFAULT_ERR_CNT,
+ KSTAT_DATA_ULONG, "rxmac_linkfault_errs"},
+ {XMAC_STAT_RX_REMOTEFAULT_ERR,
+ KSTAT_DATA_ULONG, "rxmac_remote_faults"},
+ {XMAC_STAT_RX_LOCALFAULT_ERR,
+ KSTAT_DATA_ULONG, "rxmac_local_faults"},
+ {XMAC_STAT_RX_PAUSE_CNT, KSTAT_DATA_ULONG, "rxmac_pause_cnt"},
+ {XMAC_STAT_TX_PAUSE_STATE, KSTAT_DATA_ULONG, "txmac_pause_state"},
+ {XMAC_STAT_TX_NOPAUSE_STATE, KSTAT_DATA_ULONG, "txmac_nopause_state"},
+ {XMAC_STAT_XPCS_DESKEW_ERR_CNT,
+ KSTAT_DATA_ULONG, "xpcs_deskew_err_cnt"},
+ {XMAC_STAT_XPCS_SYMBOL_L0_ERR_CNT,
+ KSTAT_DATA_ULONG, "xpcs_ln0_symbol_err_cnt"},
+ {XMAC_STAT_XPCS_SYMBOL_L1_ERR_CNT,
+ KSTAT_DATA_ULONG, "xpcs_ln1_symbol_err_cnt"},
+ {XMAC_STAT_XPCS_SYMBOL_L2_ERR_CNT,
+ KSTAT_DATA_ULONG, "xpcs_ln2_symbol_err_cnt"},
+ {XMAC_STAT_XPCS_SYMBOL_L3_ERR_CNT,
+ KSTAT_DATA_ULONG, "xpcs_ln3_symbol_err_cnt"},
+ {XMAC_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ BMAC_STAT_TX_FRAME_CNT = 0,
+ BMAC_STAT_TX_UNDERRUN_ERR,
+ BMAC_STAT_TX_MAX_PKT_ERR,
+ BMAC_STAT_TX_BYTE_CNT,
+ BMAC_STAT_RX_FRAME_CNT,
+ BMAC_STAT_RX_BYTE_CNT,
+ BMAC_STAT_RX_OVERFLOW_ERR,
+ BMAC_STAT_RX_ALIGN_ERR_CNT,
+ BMAC_STAT_RX_CRC_ERR_CNT,
+ BMAC_STAT_RX_LEN_ERR_CNT,
+ BMAC_STAT_RX_VIOL_ERR_CNT,
+ BMAC_STAT_RX_PAUSE_CNT,
+ BMAC_STAT_RX_PAUSE_STATE,
+ BMAC_STAT_RX_NOPAUSE_STATE,
+ BMAC_STAT_END
+} nxge_bmac_stat_index_t;
+
+nxge_kstat_index_t nxge_bmac_stats[] = {
+ {BMAC_STAT_TX_FRAME_CNT, KSTAT_DATA_ULONG, "txmac_frame_cnt"},
+ {BMAC_STAT_TX_UNDERRUN_ERR, KSTAT_DATA_ULONG, "txmac_underrun_err"},
+ {BMAC_STAT_TX_MAX_PKT_ERR, KSTAT_DATA_ULONG, "txmac_max_pkt_err"},
+ {BMAC_STAT_TX_BYTE_CNT, KSTAT_DATA_ULONG, "txmac_byte_cnt"},
+ {BMAC_STAT_RX_FRAME_CNT, KSTAT_DATA_ULONG, "rxmac_frame_cnt"},
+ {BMAC_STAT_RX_BYTE_CNT, KSTAT_DATA_ULONG, "rxmac_byte_cnt"},
+ {BMAC_STAT_RX_OVERFLOW_ERR, KSTAT_DATA_ULONG, "rxmac_overflow_err"},
+ {BMAC_STAT_RX_ALIGN_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_align_err_cnt"},
+ {BMAC_STAT_RX_CRC_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_crc_err_cnt"},
+ {BMAC_STAT_RX_LEN_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_len_err_cnt"},
+ {BMAC_STAT_RX_VIOL_ERR_CNT, KSTAT_DATA_ULONG, "rxmac_viol_err_cnt"},
+ {BMAC_STAT_RX_PAUSE_CNT, KSTAT_DATA_ULONG, "rxmac_pause_cnt"},
+ {BMAC_STAT_RX_PAUSE_STATE, KSTAT_DATA_ULONG, "txmac_pause_state"},
+ {BMAC_STAT_RX_NOPAUSE_STATE, KSTAT_DATA_ULONG, "tx_nopause_state"},
+ {BMAC_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ ZCP_STAT_ERRORS,
+ ZCP_STAT_INITS,
+ ZCP_STAT_RRFIFO_UNDERRUN,
+ ZCP_STAT_RRFIFO_OVERRUN,
+ ZCP_STAT_RSPFIFO_UNCORR_ERR,
+ ZCP_STAT_BUFFER_OVERFLOW,
+ ZCP_STAT_STAT_TBL_PERR,
+ ZCP_STAT_DYN_TBL_PERR,
+ ZCP_STAT_BUF_TBL_PERR,
+ ZCP_STAT_TT_PROGRAM_ERR,
+ ZCP_STAT_RSP_TT_INDEX_ERR,
+ ZCP_STAT_SLV_TT_INDEX_ERR,
+ ZCP_STAT_ZCP_TT_INDEX_ERR,
+ ZCP_STAT_ZCP_ACCESS_FAIL,
+ ZCP_CFIFO_ECC,
+ ZCP_STAT_END
+} nxge_zcp_stat_index_t;
+
+nxge_kstat_index_t nxge_zcp_stats[] = {
+ {ZCP_STAT_ERRORS, KSTAT_DATA_ULONG, "zcp_erros"},
+ {ZCP_STAT_INITS, KSTAT_DATA_ULONG, "zcp_inits"},
+ {ZCP_STAT_RRFIFO_UNDERRUN, KSTAT_DATA_ULONG, "zcp_rrfifo_underrun"},
+ {ZCP_STAT_RRFIFO_OVERRUN, KSTAT_DATA_ULONG, "zcp_rrfifo_overrun"},
+ {ZCP_STAT_RSPFIFO_UNCORR_ERR, KSTAT_DATA_ULONG,
+ "zcp_rspfifo_uncorr_err"},
+ {ZCP_STAT_BUFFER_OVERFLOW, KSTAT_DATA_ULONG, "zcp_buffer_overflow"},
+ {ZCP_STAT_STAT_TBL_PERR, KSTAT_DATA_ULONG, "zcp_stat_tbl_perr"},
+ {ZCP_STAT_DYN_TBL_PERR, KSTAT_DATA_ULONG, "zcp_dyn_tbl_perr"},
+ {ZCP_STAT_BUF_TBL_PERR, KSTAT_DATA_ULONG, "zcp_buf_tbl_perr"},
+ {ZCP_STAT_TT_PROGRAM_ERR, KSTAT_DATA_ULONG, "zcp_tt_program_err"},
+ {ZCP_STAT_RSP_TT_INDEX_ERR, KSTAT_DATA_ULONG, "zcp_rsp_tt_index_err"},
+ {ZCP_STAT_SLV_TT_INDEX_ERR, KSTAT_DATA_ULONG, "zcp_slv_tt_index_err"},
+ {ZCP_STAT_ZCP_TT_INDEX_ERR, KSTAT_DATA_ULONG, "zcp_zcp_tt_index_err"},
+ {ZCP_STAT_ZCP_ACCESS_FAIL, KSTAT_DATA_ULONG, "zcp_access_fail"},
+ {ZCP_STAT_ZCP_ACCESS_FAIL, KSTAT_DATA_ULONG, "zcp_cfifo_ecc"},
+ {ZCP_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ FFLP_STAT_TCAM_PERR,
+ FFLP_STAT_TCAM_ECC_ERR,
+ FFLP_STAT_VLAN_PERR,
+ FFLP_STAT_HASH_LOOKUP_ERR,
+ FFLP_STAT_HASH_P0_PIO_ERR,
+ FFLP_STAT_HASH_P1_PIO_ERR,
+ FFLP_STAT_HASH_P2_PIO_ERR,
+ FFLP_STAT_HASH_P3_PIO_ERR,
+ FFLP_STAT_HASH_P4_PIO_ERR,
+ FFLP_STAT_HASH_P5_PIO_ERR,
+ FFLP_STAT_HASH_P6_PIO_ERR,
+ FFLP_STAT_HASH_P7_PIO_ERR,
+ FFLP_STAT_END
+} nxge_fflp_stat_index_t;
+
+nxge_kstat_index_t nxge_fflp_stats[] = {
+ {FFLP_STAT_TCAM_PERR, KSTAT_DATA_ULONG, "fflp_tcam_perr"},
+ {FFLP_STAT_TCAM_ECC_ERR, KSTAT_DATA_ULONG, "fflp_tcam_ecc_err"},
+ {FFLP_STAT_VLAN_PERR, KSTAT_DATA_ULONG, "fflp_vlan_perr"},
+ {FFLP_STAT_HASH_LOOKUP_ERR, KSTAT_DATA_ULONG, "fflp_hash_lookup_err"},
+ {FFLP_STAT_HASH_P0_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p0_pio_err"},
+ {FFLP_STAT_HASH_P1_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p1_pio_err"},
+ {FFLP_STAT_HASH_P2_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p2_pio_err"},
+ {FFLP_STAT_HASH_P3_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p3_pio_err"},
+ {FFLP_STAT_HASH_P4_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p4_pio_err"},
+ {FFLP_STAT_HASH_P5_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p5_pio_err"},
+ {FFLP_STAT_HASH_P6_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p6_pio_err"},
+ {FFLP_STAT_HASH_P7_PIO_ERR, KSTAT_DATA_ULONG, "fflp_hash_p7_pio_err"},
+ {FFLP_STAT_END, NULL, NULL}
+};
+
+typedef enum {
+ MMAC_MAX_ADDR,
+ MMAC_AVAIL_ADDR,
+ MMAC_ADDR_POOL1,
+ MMAC_ADDR_POOL2,
+ MMAC_ADDR_POOL3,
+ MMAC_ADDR_POOL4,
+ MMAC_ADDR_POOL5,
+ MMAC_ADDR_POOL6,
+ MMAC_ADDR_POOL7,
+ MMAC_ADDR_POOL8,
+ MMAC_ADDR_POOL9,
+ MMAC_ADDR_POOL10,
+ MMAC_ADDR_POOL11,
+ MMAC_ADDR_POOL12,
+ MMAC_ADDR_POOL13,
+ MMAC_ADDR_POOL14,
+ MMAC_ADDR_POOL15,
+ MMAC_ADDR_POOL16,
+ MMAC_STATS_END
+} nxge_mmac_stat_index_t;
+
+nxge_kstat_index_t nxge_mmac_stats[] = {
+ {MMAC_MAX_ADDR, KSTAT_DATA_CHAR, "max_mmac_addr"},
+ {MMAC_AVAIL_ADDR, KSTAT_DATA_CHAR, "avail_mmac_addr"},
+ {MMAC_ADDR_POOL1, KSTAT_DATA_UINT64, "mmac_addr_1"},
+ {MMAC_ADDR_POOL2, KSTAT_DATA_UINT64, "mmac_addr_2"},
+ {MMAC_ADDR_POOL3, KSTAT_DATA_UINT64, "mmac_addr_3"},
+ {MMAC_ADDR_POOL4, KSTAT_DATA_UINT64, "mmac_addr_4"},
+ {MMAC_ADDR_POOL5, KSTAT_DATA_UINT64, "mmac_addr_5"},
+ {MMAC_ADDR_POOL6, KSTAT_DATA_UINT64, "mmac_addr_6"},
+ {MMAC_ADDR_POOL7, KSTAT_DATA_UINT64, "mmac_addr_7"},
+ {MMAC_ADDR_POOL8, KSTAT_DATA_UINT64, "mmac_addr_8"},
+ {MMAC_ADDR_POOL9, KSTAT_DATA_UINT64, "mmac_addr_9"},
+ {MMAC_ADDR_POOL10, KSTAT_DATA_UINT64, "mmac_addr_10"},
+ {MMAC_ADDR_POOL11, KSTAT_DATA_UINT64, "mmac_addr_11"},
+ {MMAC_ADDR_POOL12, KSTAT_DATA_UINT64, "mmac_addr_12"},
+ {MMAC_ADDR_POOL13, KSTAT_DATA_UINT64, "mmac_addr_13"},
+ {MMAC_ADDR_POOL14, KSTAT_DATA_UINT64, "mmac_addr_14"},
+ {MMAC_ADDR_POOL15, KSTAT_DATA_UINT64, "mmac_addr_15"},
+ {MMAC_ADDR_POOL16, KSTAT_DATA_UINT64, "mmac_addr_16"},
+ {MMAC_STATS_END, NULL, NULL},
+};
+
+int
+nxge_tdc_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_tdc_kstat_t tdc_kstatsp;
+ p_nxge_tx_ring_stats_t statsp;
+ int channel;
+ char *ch_name, *end;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_rxstat_update"));
+
+ ch_name = ksp->ks_name;
+ ch_name += strlen(TDC_NAME_FORMAT1);
+ channel = mi_strtol(ch_name, &end, 10);
+
+
+ tdc_kstatsp = (p_nxge_tdc_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_tx_ring_stats_t)&nxgep->statsp->tdc_stats[channel];
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL,
+ "nxge_tdc_stat_update data $%p statsp $%p channel %d",
+ ksp->ks_data, statsp, channel));
+
+ if (rw == KSTAT_WRITE) {
+ statsp->opackets = tdc_kstatsp->opackets.value.ull;
+ statsp->obytes = tdc_kstatsp->obytes.value.ull;
+ statsp->oerrors = tdc_kstatsp->oerrors.value.ull;
+ statsp->mbox_err = tdc_kstatsp->mbox_err.value.ul;
+ statsp->pkt_size_err = tdc_kstatsp->pkt_size_err.value.ul;
+ statsp->tx_ring_oflow = tdc_kstatsp->tx_ring_oflow.value.ul;
+ statsp->pre_buf_par_err =
+ tdc_kstatsp->pref_buf_ecc_err.value.ul;
+ statsp->nack_pref = tdc_kstatsp->nack_pref.value.ul;
+ statsp->nack_pkt_rd = tdc_kstatsp->nack_pkt_rd.value.ul;
+ statsp->conf_part_err = tdc_kstatsp->conf_part_err.value.ul;
+ statsp->pkt_part_err = tdc_kstatsp->pkt_prt_err.value.ul;
+ } else {
+ tdc_kstatsp->opackets.value.ull = statsp->opackets;
+ tdc_kstatsp->obytes.value.ull = statsp->obytes;
+ tdc_kstatsp->oerrors.value.ull = statsp->oerrors;
+ tdc_kstatsp->tx_hdr_pkts.value.ull = statsp->tx_hdr_pkts;
+ tdc_kstatsp->tx_ddi_pkts.value.ull = statsp->tx_ddi_pkts;
+ tdc_kstatsp->tx_dvma_pkts.value.ull = statsp->tx_dvma_pkts;
+ tdc_kstatsp->tx_max_pend.value.ull = statsp->tx_max_pend;
+ tdc_kstatsp->mbox_err.value.ul = statsp->mbox_err;
+ tdc_kstatsp->pkt_size_err.value.ul = statsp->pkt_size_err;
+ tdc_kstatsp->tx_ring_oflow.value.ul = statsp->tx_ring_oflow;
+ tdc_kstatsp->pref_buf_ecc_err.value.ul =
+ statsp->pre_buf_par_err;
+ tdc_kstatsp->nack_pref.value.ul = statsp->nack_pref;
+ tdc_kstatsp->nack_pkt_rd.value.ul = statsp->nack_pkt_rd;
+ tdc_kstatsp->conf_part_err.value.ul = statsp->conf_part_err;
+ tdc_kstatsp->pkt_prt_err.value.ul = statsp->pkt_part_err;
+ tdc_kstatsp->tx_starts.value.ul = statsp->tx_starts;
+ tdc_kstatsp->tx_nocanput.value.ul = statsp->tx_nocanput;
+ tdc_kstatsp->tx_msgdup_fail.value.ul = statsp->tx_msgdup_fail;
+ tdc_kstatsp->tx_allocb_fail.value.ul = statsp->tx_allocb_fail;
+ tdc_kstatsp->tx_no_desc.value.ul = statsp->tx_no_desc;
+ tdc_kstatsp->tx_dma_bind_fail.value.ul =
+ statsp->tx_dma_bind_fail;
+
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, " <== nxge_tdc_stat_update"));
+ return (0);
+}
+
+int
+nxge_rdc_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_rdc_kstat_t rdc_kstatsp;
+ p_nxge_rx_ring_stats_t statsp;
+ int channel;
+ char *ch_name, *end;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_rdc_stat_update"));
+
+ ch_name = ksp->ks_name;
+ ch_name += strlen(RDC_NAME_FORMAT1);
+ channel = mi_strtol(ch_name, &end, 10);
+
+ rdc_kstatsp = (p_nxge_rdc_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_rx_ring_stats_t)&nxgep->statsp->rdc_stats[channel];
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL,
+ "nxge_rdc_stat_update $%p statsp $%p channel %d",
+ ksp->ks_data, statsp, channel));
+
+ if (rw == KSTAT_WRITE) {
+ statsp->dcf_err = rdc_kstatsp->dcf_err.value.ul;
+ statsp->rcr_ack_err = rdc_kstatsp->rcr_ack_err.value.ul;
+ statsp->dc_fifo_err = rdc_kstatsp->dc_fifoflow_err.value.ul;
+ statsp->rcr_sha_par = rdc_kstatsp->rcr_sha_par_err.value.ul;
+ statsp->rbr_pre_par = rdc_kstatsp->rbr_pre_par_err.value.ul;
+ statsp->wred_drop = rdc_kstatsp->wred_drop.value.ul;
+ statsp->rbr_pre_empty = rdc_kstatsp->rbr_pre_emty.value.ul;
+ statsp->rcr_shadow_full = rdc_kstatsp->rcr_shadow_full.value.ul;
+ statsp->rx_rbr_tmout = rdc_kstatsp->rbr_tmout.value.ul;
+ statsp->rsp_cnt_err = rdc_kstatsp->rsp_cnt_err.value.ul;
+ statsp->byte_en_bus = rdc_kstatsp->byte_en_bus.value.ul;
+ statsp->rsp_dat_err = rdc_kstatsp->rsp_dat_err.value.ul;
+ statsp->l2_err = rdc_kstatsp->compl_l2_err.value.ul;
+ statsp->l4_cksum_err = rdc_kstatsp->compl_l4_cksum_err.value.ul;
+ statsp->fflp_soft_err =
+ rdc_kstatsp->compl_fflp_soft_err.value.ul;
+ statsp->zcp_soft_err = rdc_kstatsp->compl_zcp_soft_err.value.ul;
+ statsp->config_err = rdc_kstatsp->config_err.value.ul;
+ statsp->rcrincon = rdc_kstatsp->rcrincon.value.ul;
+ statsp->rcrfull = rdc_kstatsp->rcrfull.value.ul;
+ statsp->rbr_empty = rdc_kstatsp->rbr_empty.value.ul;
+ statsp->rbrfull = rdc_kstatsp->rbrfull.value.ul;
+ statsp->rbrlogpage = rdc_kstatsp->rbrlogpage.value.ul;
+ statsp->cfiglogpage = rdc_kstatsp->cfiglogpage.value.ul;
+ } else {
+ rdc_kstatsp->ipackets.value.ull = statsp->ipackets;
+ rdc_kstatsp->rbytes.value.ull = statsp->ibytes;
+ rdc_kstatsp->errors.value.ul = statsp->ierrors;
+ rdc_kstatsp->dcf_err.value.ul = statsp->dcf_err;
+ rdc_kstatsp->rcr_ack_err.value.ul = statsp->rcr_ack_err;
+ rdc_kstatsp->dc_fifoflow_err.value.ul = statsp->dc_fifo_err;
+ rdc_kstatsp->rcr_sha_par_err.value.ul = statsp->rcr_sha_par;
+ rdc_kstatsp->rbr_pre_par_err.value.ul = statsp->rbr_pre_par;
+ rdc_kstatsp->wred_drop.value.ul = statsp->wred_drop;
+ rdc_kstatsp->port_drop_pkt.value.ul = statsp->port_drop_pkt;
+ rdc_kstatsp->rbr_pre_emty.value.ul = statsp->rbr_pre_empty;
+ rdc_kstatsp->rcr_shadow_full.value.ul = statsp->rcr_shadow_full;
+ rdc_kstatsp->rbr_tmout.value.ul = statsp->rx_rbr_tmout;
+ rdc_kstatsp->rsp_cnt_err.value.ul = statsp->rsp_cnt_err;
+ rdc_kstatsp->byte_en_bus.value.ul = statsp->byte_en_bus;
+ rdc_kstatsp->rsp_dat_err.value.ul = statsp->rsp_dat_err;
+ rdc_kstatsp->compl_l2_err.value.ul = statsp->l2_err;
+ rdc_kstatsp->compl_l4_cksum_err.value.ul = statsp->l4_cksum_err;
+ rdc_kstatsp->compl_fflp_soft_err.value.ul =
+ statsp->fflp_soft_err;
+ rdc_kstatsp->compl_zcp_soft_err.value.ul = statsp->zcp_soft_err;
+ rdc_kstatsp->config_err.value.ul = statsp->config_err;
+ rdc_kstatsp->rcrincon.value.ul = statsp->rcrincon;
+ rdc_kstatsp->rcrfull.value.ul = statsp->rcrfull;
+ rdc_kstatsp->rbr_empty.value.ul = statsp->rbr_empty;
+ rdc_kstatsp->rbrfull.value.ul = statsp->rbrfull;
+ rdc_kstatsp->rbrlogpage.value.ul = statsp->rbrlogpage;
+ rdc_kstatsp->cfiglogpage.value.ul = statsp->cfiglogpage;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, " <== nxge_rdc_stat_update"));
+ return (0);
+}
+
+int
+nxge_rdc_sys_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_rdc_sys_kstat_t rdc_sys_kstatsp;
+ p_nxge_rdc_sys_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_rdc_sys_stat_update"));
+
+ rdc_sys_kstatsp = (p_nxge_rdc_sys_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_rdc_sys_stats_t)&nxgep->statsp->rdc_sys_stats;
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "nxge_rdc_sys_stat_update %llx",
+ ksp->ks_data));
+
+ if (rw == KSTAT_WRITE) {
+ statsp->id_mismatch = rdc_sys_kstatsp->id_mismatch.value.ul;
+ statsp->ipp_eop_err = rdc_sys_kstatsp->ipp_eop_err.value.ul;
+ statsp->zcp_eop_err = rdc_sys_kstatsp->zcp_eop_err.value.ul;
+ } else {
+ rdc_sys_kstatsp->id_mismatch.value.ul = statsp->id_mismatch;
+ rdc_sys_kstatsp->ipp_eop_err.value.ul = statsp->ipp_eop_err;
+ rdc_sys_kstatsp->zcp_eop_err.value.ul = statsp->zcp_eop_err;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, " <== nxge_rdc_sys_stat_update"));
+ return (0);
+}
+
+
+
+static int
+nxge_txc_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_txc_kstat_t txc_kstatsp;
+ p_nxge_txc_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_txc_stat_update"));
+
+ txc_kstatsp = (p_nxge_txc_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
+
+ if (rw == KSTAT_WRITE) {
+
+ statsp->pkt_stuffed = txc_kstatsp->pkt_stuffed.value.ul;
+ statsp->pkt_xmit = txc_kstatsp->pkt_xmit.value.ul;
+ statsp->ro_correct_err = txc_kstatsp->ro_correct_err.value.ul;
+ statsp->ro_uncorrect_err =
+ txc_kstatsp->ro_uncorrect_err.value.ul;
+ statsp->sf_correct_err = txc_kstatsp->sf_correct_err.value.ul;
+ statsp->sf_uncorrect_err =
+ txc_kstatsp->sf_uncorrect_err.value.ul;
+ statsp->address_failed = txc_kstatsp->address_failed.value.ul;
+ statsp->dma_failed = txc_kstatsp->dma_failed.value.ul;
+ statsp->length_failed = txc_kstatsp->length_failed.value.ul;
+ statsp->pkt_assy_dead = txc_kstatsp->pkt_assy_dead.value.ul;
+ statsp->reorder_err = txc_kstatsp->reorder_err.value.ul;
+ } else {
+ txc_kstatsp->pkt_stuffed.value.ul = statsp->pkt_stuffed;
+ txc_kstatsp->pkt_xmit.value.ul = statsp->pkt_xmit;
+ txc_kstatsp->ro_correct_err.value.ul = statsp->ro_correct_err;
+ txc_kstatsp->ro_uncorrect_err.value.ul =
+ statsp->ro_uncorrect_err;
+ txc_kstatsp->sf_correct_err.value.ul = statsp->sf_correct_err;
+ txc_kstatsp->sf_uncorrect_err.value.ul =
+ statsp->sf_uncorrect_err;
+ txc_kstatsp->address_failed.value.ul = statsp->address_failed;
+ txc_kstatsp->dma_failed.value.ul = statsp->dma_failed;
+ txc_kstatsp->length_failed.value.ul = statsp->length_failed;
+ txc_kstatsp->pkt_assy_dead.value.ul = statsp->pkt_assy_dead;
+ txc_kstatsp->reorder_err.value.ul = statsp->reorder_err;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_txc_stat_update"));
+ return (0);
+}
+
+int
+nxge_ipp_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_ipp_kstat_t ipp_kstatsp;
+ p_nxge_ipp_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_ipp_stat_update"));
+
+ ipp_kstatsp = (p_nxge_ipp_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats;
+
+ if (rw == KSTAT_WRITE) {
+ statsp->eop_miss = ipp_kstatsp->eop_miss.value.ul;
+ statsp->sop_miss = ipp_kstatsp->sop_miss.value.ul;
+ statsp->dfifo_ue = ipp_kstatsp->dfifo_ue.value.ul;
+ statsp->ecc_err_cnt = ipp_kstatsp->ecc_err_cnt.value.ul;
+ statsp->pfifo_over = ipp_kstatsp->pfifo_over.value.ul;
+ statsp->pfifo_und = ipp_kstatsp->pfifo_und.value.ul;
+ statsp->bad_cs_cnt = ipp_kstatsp->bad_cs_cnt.value.ul;
+ statsp->pkt_dis_cnt = ipp_kstatsp->pkt_dis_cnt.value.ul;
+ statsp->bad_cs_cnt = ipp_kstatsp->cs_fail.value.ul;
+ } else {
+ ipp_kstatsp->eop_miss.value.ul = statsp->eop_miss;
+ ipp_kstatsp->sop_miss.value.ul = statsp->sop_miss;
+ ipp_kstatsp->dfifo_ue.value.ul = statsp->dfifo_ue;
+ ipp_kstatsp->ecc_err_cnt.value.ul = statsp->ecc_err_cnt;
+ ipp_kstatsp->pfifo_over.value.ul = statsp->pfifo_over;
+ ipp_kstatsp->pfifo_und.value.ul = statsp->pfifo_und;
+ ipp_kstatsp->bad_cs_cnt.value.ul = statsp->bad_cs_cnt;
+ ipp_kstatsp->pkt_dis_cnt.value.ul = statsp->pkt_dis_cnt;
+ ipp_kstatsp->cs_fail.value.ul = statsp->bad_cs_cnt;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_ipp_stat_update"));
+ return (0);
+}
+
+int
+nxge_xmac_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_xmac_kstat_t xmac_kstatsp;
+ p_nxge_xmac_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_xmac_stat_update"));
+
+ xmac_kstatsp = (p_nxge_xmac_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_xmac_stats_t)&nxgep->statsp->xmac_stats;
+
+ if (rw == KSTAT_WRITE) {
+ statsp->tx_frame_cnt = xmac_kstatsp->tx_frame_cnt.value.ul;
+ statsp->tx_underflow_err =
+ xmac_kstatsp->tx_underflow_err.value.ul;
+ statsp->tx_maxpktsize_err =
+ xmac_kstatsp->tx_maxpktsize_err.value.ul;
+ statsp->tx_overflow_err =
+ xmac_kstatsp->tx_overflow_err.value.ul;
+ statsp->tx_fifo_xfr_err =
+ xmac_kstatsp->tx_fifo_xfr_err.value.ul;
+ statsp->tx_byte_cnt = xmac_kstatsp->tx_byte_cnt.value.ul;
+ statsp->rx_underflow_err =
+ xmac_kstatsp->rx_underflow_err.value.ul;
+ statsp->rx_overflow_err =
+ xmac_kstatsp->rx_overflow_err.value.ul;
+ statsp->rx_crc_err_cnt = xmac_kstatsp->rx_crc_err_cnt.value.ul;
+ statsp->rx_len_err_cnt = xmac_kstatsp->rx_len_err_cnt.value.ul;
+ statsp->rx_viol_err_cnt =
+ xmac_kstatsp->rx_viol_err_cnt.value.ul;
+ statsp->rx_byte_cnt = xmac_kstatsp->rx_byte_cnt.value.ul;
+ statsp->rx_hist1_cnt = xmac_kstatsp->rx_hist1_cnt.value.ul;
+ statsp->rx_hist2_cnt = xmac_kstatsp->rx_hist2_cnt.value.ul;
+ statsp->rx_hist3_cnt = xmac_kstatsp->rx_hist3_cnt.value.ul;
+ statsp->rx_hist4_cnt = xmac_kstatsp->rx_hist4_cnt.value.ul;
+ statsp->rx_hist5_cnt = xmac_kstatsp->rx_hist5_cnt.value.ul;
+ statsp->rx_hist6_cnt = xmac_kstatsp->rx_hist6_cnt.value.ul;
+ statsp->rx_mult_cnt = xmac_kstatsp->rx_mult_cnt.value.ul;
+ statsp->rx_frag_cnt = xmac_kstatsp->rx_frag_cnt.value.ul;
+ statsp->rx_frame_align_err_cnt =
+ xmac_kstatsp->rx_frame_align_err_cnt.value.ul;
+ statsp->rx_linkfault_err_cnt =
+ xmac_kstatsp->rx_linkfault_err_cnt.value.ul;
+ statsp->rx_localfault_err =
+ xmac_kstatsp->rx_local_fault_err_cnt.value.ul;
+ statsp->rx_remotefault_err =
+ xmac_kstatsp->rx_remote_fault_err_cnt.value.ul;
+ statsp->xpcs_deskew_err_cnt =
+ xmac_kstatsp->xpcs_deskew_err_cnt.value.ul;
+ statsp->xpcs_ln0_symbol_err_cnt =
+ xmac_kstatsp->xpcs_ln0_symbol_err_cnt.value.ul;
+ statsp->xpcs_ln1_symbol_err_cnt =
+ xmac_kstatsp->xpcs_ln1_symbol_err_cnt.value.ul;
+ statsp->xpcs_ln2_symbol_err_cnt =
+ xmac_kstatsp->xpcs_ln2_symbol_err_cnt.value.ul;
+ statsp->xpcs_ln3_symbol_err_cnt =
+ xmac_kstatsp->xpcs_ln3_symbol_err_cnt.value.ul;
+ } else {
+ xmac_kstatsp->tx_frame_cnt.value.ul = statsp->tx_frame_cnt;
+ xmac_kstatsp->tx_underflow_err.value.ul =
+ statsp->tx_underflow_err;
+ xmac_kstatsp->tx_maxpktsize_err.value.ul =
+ statsp->tx_maxpktsize_err;
+ xmac_kstatsp->tx_overflow_err.value.ul =
+ statsp->tx_overflow_err;
+ xmac_kstatsp->tx_fifo_xfr_err.value.ul =
+ statsp->tx_fifo_xfr_err;
+ xmac_kstatsp->tx_byte_cnt.value.ul = statsp->tx_byte_cnt;
+ xmac_kstatsp->rx_underflow_err.value.ul =
+ statsp->rx_underflow_err;
+ xmac_kstatsp->rx_overflow_err.value.ul =
+ statsp->rx_overflow_err;
+ xmac_kstatsp->rx_crc_err_cnt.value.ul = statsp->rx_crc_err_cnt;
+ xmac_kstatsp->rx_len_err_cnt.value.ul = statsp->rx_len_err_cnt;
+ xmac_kstatsp->rx_viol_err_cnt.value.ul =
+ statsp->rx_viol_err_cnt;
+ xmac_kstatsp->rx_byte_cnt.value.ul = statsp->rx_byte_cnt;
+ xmac_kstatsp->rx_hist1_cnt.value.ul = statsp->rx_hist1_cnt;
+ xmac_kstatsp->rx_hist2_cnt.value.ul = statsp->rx_hist2_cnt;
+ xmac_kstatsp->rx_hist3_cnt.value.ul = statsp->rx_hist3_cnt;
+ xmac_kstatsp->rx_hist4_cnt.value.ul = statsp->rx_hist4_cnt;
+ xmac_kstatsp->rx_hist5_cnt.value.ul = statsp->rx_hist5_cnt;
+ xmac_kstatsp->rx_hist6_cnt.value.ul = statsp->rx_hist6_cnt;
+ xmac_kstatsp->rx_mult_cnt.value.ul = statsp->rx_mult_cnt;
+ xmac_kstatsp->rx_frag_cnt.value.ul = statsp->rx_frag_cnt;
+ xmac_kstatsp->rx_frame_align_err_cnt.value.ul =
+ statsp->rx_frame_align_err_cnt;
+ xmac_kstatsp->rx_linkfault_err_cnt.value.ul =
+ statsp->rx_linkfault_err_cnt;
+ xmac_kstatsp->rx_local_fault_err_cnt.value.ul =
+ statsp->rx_localfault_err;
+ xmac_kstatsp->rx_remote_fault_err_cnt.value.ul =
+ statsp->rx_remotefault_err;
+ xmac_kstatsp->xpcs_deskew_err_cnt.value.ul =
+ statsp->xpcs_deskew_err_cnt;
+ xmac_kstatsp->xpcs_ln0_symbol_err_cnt.value.ul =
+ statsp->xpcs_ln0_symbol_err_cnt;
+ xmac_kstatsp->xpcs_ln1_symbol_err_cnt.value.ul =
+ statsp->xpcs_ln1_symbol_err_cnt;
+ xmac_kstatsp->xpcs_ln2_symbol_err_cnt.value.ul =
+ statsp->xpcs_ln2_symbol_err_cnt;
+ xmac_kstatsp->xpcs_ln3_symbol_err_cnt.value.ul =
+ statsp->xpcs_ln3_symbol_err_cnt;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_xmac_stat_update"));
+ return (0);
+}
+
+int
+nxge_bmac_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_bmac_kstat_t bmac_kstatsp;
+ p_nxge_bmac_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_bmac_stat_update"));
+
+ bmac_kstatsp = (p_nxge_bmac_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_bmac_stats_t)&nxgep->statsp->bmac_stats;
+
+ if (rw == KSTAT_WRITE) {
+ statsp->tx_frame_cnt = bmac_kstatsp->tx_frame_cnt.value.ul;
+ statsp->tx_underrun_err =
+ bmac_kstatsp->tx_underrun_err.value.ul;
+ statsp->tx_max_pkt_err = bmac_kstatsp->tx_max_pkt_err.value.ul;
+ statsp->tx_byte_cnt = bmac_kstatsp->tx_byte_cnt.value.ul;
+ statsp->rx_frame_cnt = bmac_kstatsp->rx_frame_cnt.value.ul;
+ statsp->rx_byte_cnt = bmac_kstatsp->rx_byte_cnt.value.ul;
+ statsp->rx_overflow_err =
+ bmac_kstatsp->rx_overflow_err.value.ul;
+ statsp->rx_align_err_cnt =
+ bmac_kstatsp->rx_align_err_cnt.value.ul;
+ statsp->rx_crc_err_cnt = bmac_kstatsp->rx_crc_err_cnt.value.ul;
+ statsp->rx_len_err_cnt = bmac_kstatsp->rx_len_err_cnt.value.ul;
+ statsp->rx_viol_err_cnt =
+ bmac_kstatsp->rx_viol_err_cnt.value.ul;
+ } else {
+ bmac_kstatsp->tx_frame_cnt.value.ul = statsp->tx_frame_cnt;
+ bmac_kstatsp->tx_underrun_err.value.ul =
+ statsp->tx_underrun_err;
+ bmac_kstatsp->tx_max_pkt_err.value.ul = statsp->tx_max_pkt_err;
+ bmac_kstatsp->tx_byte_cnt.value.ul = statsp->tx_byte_cnt;
+ bmac_kstatsp->rx_frame_cnt.value.ul = statsp->rx_frame_cnt;
+ bmac_kstatsp->rx_byte_cnt.value.ul = statsp->rx_byte_cnt;
+ bmac_kstatsp->rx_overflow_err.value.ul =
+ statsp->rx_overflow_err;
+ bmac_kstatsp->rx_align_err_cnt.value.ul =
+ statsp->rx_align_err_cnt;
+ bmac_kstatsp->rx_crc_err_cnt.value.ul = statsp->rx_crc_err_cnt;
+ bmac_kstatsp->rx_len_err_cnt.value.ul = statsp->rx_len_err_cnt;
+ bmac_kstatsp->rx_viol_err_cnt.value.ul =
+ statsp->rx_viol_err_cnt;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_bmac_stat_update"));
+ return (0);
+}
+
+int
+nxge_zcp_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_zcp_kstat_t zcp_kstatsp;
+ p_nxge_zcp_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_zcp_stat_update"));
+
+ zcp_kstatsp = (p_nxge_zcp_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
+
+ if (rw == KSTAT_WRITE) {
+ statsp->rrfifo_underrun = zcp_kstatsp->rrfifo_underrun.value.ul;
+ statsp->rrfifo_overrun = zcp_kstatsp->rrfifo_overrun.value.ul;
+ statsp->rspfifo_uncorr_err =
+ zcp_kstatsp->rspfifo_uncorr_err.value.ul;
+ statsp->buffer_overflow = zcp_kstatsp->buffer_overflow.value.ul;
+ statsp->stat_tbl_perr = zcp_kstatsp->stat_tbl_perr.value.ul;
+ statsp->dyn_tbl_perr = zcp_kstatsp->dyn_tbl_perr.value.ul;
+ statsp->buf_tbl_perr = zcp_kstatsp->buf_tbl_perr.value.ul;
+ statsp->tt_program_err = zcp_kstatsp->tt_program_err.value.ul;
+ statsp->rsp_tt_index_err =
+ zcp_kstatsp->rsp_tt_index_err.value.ul;
+ statsp->slv_tt_index_err =
+ zcp_kstatsp->slv_tt_index_err.value.ul;
+ statsp->zcp_tt_index_err =
+ zcp_kstatsp->zcp_tt_index_err.value.ul;
+ statsp->cfifo_ecc = zcp_kstatsp->cfifo_ecc.value.ul;
+ } else {
+ zcp_kstatsp->rrfifo_underrun.value.ul = statsp->rrfifo_underrun;
+ zcp_kstatsp->rrfifo_overrun.value.ul = statsp->rrfifo_overrun;
+ zcp_kstatsp->rspfifo_uncorr_err.value.ul =
+ statsp->rspfifo_uncorr_err;
+ zcp_kstatsp->buffer_overflow.value.ul =
+ statsp->buffer_overflow;
+ zcp_kstatsp->stat_tbl_perr.value.ul = statsp->stat_tbl_perr;
+ zcp_kstatsp->dyn_tbl_perr.value.ul = statsp->dyn_tbl_perr;
+ zcp_kstatsp->buf_tbl_perr.value.ul = statsp->buf_tbl_perr;
+ zcp_kstatsp->tt_program_err.value.ul = statsp->tt_program_err;
+ zcp_kstatsp->rsp_tt_index_err.value.ul =
+ statsp->rsp_tt_index_err;
+ zcp_kstatsp->slv_tt_index_err.value.ul =
+ statsp->slv_tt_index_err;
+ zcp_kstatsp->zcp_tt_index_err.value.ul =
+ statsp->zcp_tt_index_err;
+ zcp_kstatsp->cfifo_ecc.value.ul = statsp->cfifo_ecc;
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_zcp_stat_update"));
+ return (0);
+}
+
+int
+nxge_fflp_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_fflp_kstat_t fflp_kstatsp;
+ p_nxge_fflp_stats_t statsp;
+ int ldc_grp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_fflp_stat_update"));
+
+ fflp_kstatsp = (p_nxge_fflp_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_fflp_stats_t)&nxgep->statsp->fflp_stats;
+
+ if (rw == KSTAT_WRITE) {
+ statsp->tcam_parity_err = fflp_kstatsp->fflp_tcam_perr.value.ul;
+ statsp->tcam_ecc_err = fflp_kstatsp->fflp_tcam_ecc_err.value.ul;
+ statsp->vlan_parity_err = fflp_kstatsp->fflp_vlan_perr.value.ul;
+ statsp->hash_lookup_err =
+ fflp_kstatsp->fflp_hasht_lookup_err.value.ul;
+ for (ldc_grp = 0; ldc_grp < MAX_PARTITION; ldc_grp++) {
+ statsp->hash_pio_err[ldc_grp] =
+ fflp_kstatsp->fflp_hasht_data_err[ldc_grp].
+ value.ul;
+ }
+ } else {
+ fflp_kstatsp->fflp_tcam_perr.value.ul =
+ fflp_kstatsp->fflp_tcam_perr.value.ul;
+ fflp_kstatsp->fflp_tcam_ecc_err.value.ul = statsp->tcam_ecc_err;
+ fflp_kstatsp->fflp_vlan_perr.value.ul = statsp->vlan_parity_err;
+ fflp_kstatsp->fflp_hasht_lookup_err.value.ul =
+ statsp->hash_lookup_err;
+ for (ldc_grp = 0; ldc_grp < MAX_PARTITION; ldc_grp++) {
+ fflp_kstatsp->fflp_hasht_data_err[ldc_grp].value.ul =
+ statsp->hash_pio_err[ldc_grp];
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_fflp_stat_update"));
+ return (0);
+}
+
+static uint64_t
+nxge_mac_octet_to_u64(struct ether_addr addr)
+{
+ int i;
+ uint64_t addr64 = 0;
+ for (i = ETHERADDRL - 1; i >= 0; i--) {
+ addr64 <<= 8;
+ addr64 |= addr.ether_addr_octet[i];
+ }
+ return (addr64);
+}
+
+int
+nxge_mmac_stat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_mmac_kstat_t mmac_kstatsp;
+ p_nxge_mmac_stats_t statsp;
+
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_mmac_stat_update"));
+
+ mmac_kstatsp = (p_nxge_mmac_kstat_t)ksp->ks_data;
+ statsp = (p_nxge_mmac_stats_t)&nxgep->statsp->mmac_stats;
+
+ if (rw == KSTAT_WRITE) {
+ cmn_err(CE_WARN, "Can not write mmac stats");
+ } else {
+ mmac_kstatsp->mmac_max_addr_cnt.value.ul =
+ statsp->mmac_max_cnt;
+ mmac_kstatsp->mmac_avail_addr_cnt.value.ul =
+ statsp->mmac_avail_cnt;
+ mmac_kstatsp->mmac_addr1.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[0]);
+ mmac_kstatsp->mmac_addr2.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[1]);
+ mmac_kstatsp->mmac_addr3.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[2]);
+ mmac_kstatsp->mmac_addr4.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[3]);
+ mmac_kstatsp->mmac_addr5.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[4]);
+ mmac_kstatsp->mmac_addr6.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[5]);
+ mmac_kstatsp->mmac_addr7.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[6]);
+ mmac_kstatsp->mmac_addr8.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[7]);
+ mmac_kstatsp->mmac_addr9.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[8]);
+ mmac_kstatsp->mmac_addr10.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[9]);
+ mmac_kstatsp->mmac_addr11.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[10]);
+ mmac_kstatsp->mmac_addr12.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[11]);
+ mmac_kstatsp->mmac_addr13.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[12]);
+ mmac_kstatsp->mmac_addr14.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[13]);
+ mmac_kstatsp->mmac_addr15.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[14]);
+ mmac_kstatsp->mmac_addr16.value.ul =
+ nxge_mac_octet_to_u64(statsp->mmac_avail_pool[15]);
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_mmac_stat_update"));
+ return (0);
+}
+
+static kstat_t *
+nxge_setup_local_kstat(p_nxge_t nxgep, int instance, char *name,
+ const nxge_kstat_index_t *ksip,
+ size_t count,
+ int (*update)(kstat_t *, int))
+{
+ kstat_t *ksp;
+ kstat_named_t *knp;
+ int i;
+ ksp = kstat_create(NXGE_DRIVER_NAME, instance, name, "net",
+ KSTAT_TYPE_NAMED, count, 0);
+ if (ksp == NULL)
+ return (NULL);
+
+ ksp->ks_private = (void *)nxgep;
+ ksp->ks_update = update;
+ knp = ksp->ks_data;
+
+ for (i = 0; ksip[i].name != NULL; i++) {
+ kstat_named_init(&knp[i], ksip[i].name, ksip[i].type);
+ }
+
+ kstat_install(ksp);
+
+ return (ksp);
+}
+
+
+void
+nxge_setup_kstats(p_nxge_t nxgep)
+{
+ struct kstat *ksp;
+ p_nxge_port_kstat_t nxgekp;
+ size_t nxge_kstat_sz;
+ char stat_name[64];
+ char mmac_name[64];
+ int i;
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_setup_kstats"));
+
+
+ /* Setup RDC statistics */
+ for (i = 0; i < nxgep->nrdc; i++) {
+ (void) sprintf(stat_name, "%s" CH_NAME_FORMAT,
+ RDC_NAME_FORMAT1, i);
+ nxgep->statsp->rdc_ksp[i] = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ stat_name,
+ &nxge_rdc_stats[0],
+ RDC_STAT_END,
+ nxge_rdc_stat_update);
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->statsp->rdc_ksp[i] == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL,
+ "kstat_create failed for rdc channel %d",
+ i));
+#endif
+ }
+
+ /* Setup RDC System statistics */
+ nxgep->statsp->rdc_sys_ksp = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "RDC System Stats",
+ &nxge_rdc_sys_stats[0],
+ RDC_SYS_STAT_END,
+ nxge_rdc_sys_stat_update);
+
+ /* Setup IPP statistics */
+ nxgep->statsp->ipp_ksp = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "IPP Stats",
+ &nxge_ipp_stats[0],
+ IPP_STAT_END,
+ nxge_ipp_stat_update);
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->istatsp->pp_ksp == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "kstat_create failed for ipp"));
+#endif
+
+ /* Setup TDC statistics */
+ for (i = 0; i < nxgep->ntdc; i++) {
+ (void) sprintf(stat_name, "%s" CH_NAME_FORMAT,
+ TDC_NAME_FORMAT1, i);
+ nxgep->statsp->tdc_ksp[i] = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ stat_name,
+ &nxge_tdc_stats[0],
+ TDC_STAT_END,
+ nxge_tdc_stat_update);
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->statsp->tdc_ksp[i] == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL,
+ "kstat_create failed for tdc channel %d",
+ i));
+#endif
+ }
+
+ /* Setup TXC statistics */
+ nxgep->statsp->txc_ksp = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "TXC Stats",
+ &nxge_txc_stats[0],
+ TXC_STAT_END,
+ nxge_txc_stat_update);
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->statsp->txc_ksp == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "kstat_create failed for txc"));
+#endif
+
+
+ /* Setup ZCP statistics */
+ nxgep->statsp->zcp_ksp = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "ZCP Stats",
+ &nxge_zcp_stats[0],
+ ZCP_STAT_END,
+ nxge_zcp_stat_update);
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->statsp->zcp_ksp == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "kstat_create failed for zcp"));
+#endif
+
+ /* Setup FFLP statistics */
+ nxgep->statsp->fflp_ksp[0] = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "FFLP Stats",
+ &nxge_fflp_stats[0],
+ FFLP_STAT_END,
+ nxge_fflp_stat_update);
+
+#ifdef NXGE_DEBUG_ERROR
+ if (nxgep->statsp->fflp_ksp == NULL)
+ NXGE_DEBUG_MSG((nxgep, KST_CTL,
+ "kstat_create failed for fflp"));
+#endif
+
+ (void) sprintf(mmac_name, "MMAC Stats%d", nxgep->instance);
+ nxgep->statsp->mmac_ksp = nxge_setup_local_kstat(nxgep,
+ nxgep->instance,
+ "MMAC Stats",
+ &nxge_mmac_stats[0],
+ MMAC_STATS_END,
+ nxge_mmac_stat_update);
+
+ nxge_kstat_sz = sizeof (nxge_port_kstat_t) +
+ sizeof (nxge_mac_kstat_t) - sizeof (kstat_named_t);
+
+ if ((ksp = kstat_create(NXGE_DRIVER_NAME, nxgep->instance,
+ "Port Stats", "net", KSTAT_TYPE_NAMED,
+ nxge_kstat_sz / sizeof (kstat_named_t), 0)) == NULL) {
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "kstat_create failed"));
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_setup_kstats"));
+ return;
+ }
+
+ nxgekp = (p_nxge_port_kstat_t)ksp->ks_data;
+ kstat_named_init(&nxgekp->ipackets, "ipackets",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->ipackets64, "ipackets64",
+ KSTAT_DATA_ULONGLONG);
+ kstat_named_init(&nxgekp->ierrors, "ierrors",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->opackets, "opackets",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->opackets64, "opackets64",
+ KSTAT_DATA_ULONGLONG);
+ kstat_named_init(&nxgekp->oerrors, "oerrors",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->collisions, "collisions",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * MIB II kstat variables
+ */
+ kstat_named_init(&nxgekp->rbytes, "rbytes",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rbytes64, "rbytes64",
+ KSTAT_DATA_ULONGLONG);
+ kstat_named_init(&nxgekp->obytes, "obytes",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->obytes64, "obytes64",
+ KSTAT_DATA_ULONGLONG);
+ kstat_named_init(&nxgekp->multircv, "multircv",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->multixmt, "multixmt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->brdcstrcv, "brdcstrcv",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->brdcstxmt, "brdcstxmt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->norcvbuf, "norcvbuf",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->noxmtbuf, "noxmtbuf",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * transceiver state informations.
+ */
+ kstat_named_init(&nxgekp->xcvr_inits, "xcvr_inits",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xcvr_inuse, "xcvr_inuse",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xcvr_addr, "xcvr_addr",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xcvr_id, "xcvr_id",
+ KSTAT_DATA_ULONG);
+
+ kstat_named_init(&nxgekp->cap_autoneg, "cap_autoneg",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_10gfdx, "cap_10gfdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_10ghdx, "cap_10ghdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_1000fdx, "cap_1000fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_1000hdx, "cap_1000hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_100T4, "cap_100T4",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_100fdx, "cap_100fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_100hdx, "cap_100hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_10fdx, "cap_10fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_10hdx, "cap_10hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_asmpause, "cap_asmpause",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->cap_pause, "cap_pause",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * Link partner capabilities.
+ */
+ kstat_named_init(&nxgekp->lp_cap_autoneg, "lp_cap_autoneg",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_10gfdx, "lp_cap_10gfdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_10ghdx, "lp_cap_10ghdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_1000fdx, "lp_cap_1000fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_1000hdx, "lp_cap_1000hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_100T4, "lp_cap_100T4",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_100fdx, "lp_cap_100fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_100hdx, "lp_cap_100hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_10fdx, "lp_cap_10fdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_10hdx, "lp_cap_10hdx",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_asmpause, "lp_cap_asmpause",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->lp_cap_pause, "lp_cap_pause",
+ KSTAT_DATA_ULONG);
+ /*
+ * Shared link setup.
+ */
+ kstat_named_init(&nxgekp->link_T4, "link_T4",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->link_speed, "link_speed",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->link_duplex, "link_duplex",
+ KSTAT_DATA_CHAR);
+ kstat_named_init(&nxgekp->link_asmpause, "link_asmpause",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->link_pause, "link_pause",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->link_up, "link_up",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * Lets the user know the MTU currently in use by
+ * the physical MAC port.
+ */
+ kstat_named_init(&nxgekp->mac_mtu, "mac_mtu",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * Loopback statistics.
+ */
+ kstat_named_init(&nxgekp->lb_mode, "lb_mode",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * This tells the user whether the driver is in QOS mode
+ * or not.
+ */
+ kstat_named_init(&nxgekp->qos_mode, "qos_mode",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * This tells whether the instance is trunked or not
+ */
+ kstat_named_init(&nxgekp->trunk_mode, "trunk_mode",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * Tx Statistics.
+ */
+ kstat_named_init(&nxgekp->tx_inits, "tx_inits",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_starts, "tx_starts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_nocanput, "tx_nocanput",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_msgdup_fail, "tx_msgdup_fail",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_allocb_fail, "tx_allocb_fail",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_no_desc, "tx_no_desc",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_dma_bind_fail, "tx_dma_bind_fail",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_uflo, "tx_uflo",
+ KSTAT_DATA_ULONG);
+
+ kstat_named_init(&nxgekp->tx_hdr_pkts, "tx_hdr_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_ddi_pkts, "tx_ddi_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_dvma_pkts, "tx_dvma_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_max_pend, "tx_max_pend",
+ KSTAT_DATA_ULONG);
+#if defined MULTI_DATA_TX || defined MULTI_DATA_TXV2
+ kstat_named_init(&nxgekp->mdt_reqs, "mdt_reqs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_hdr_bufs, "mdt_hdr_bufs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_pld_bufs, "mdt_pld_bufs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_pkts, "mdt_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_hdrs, "mdt_hdrs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_plds, "mdt_plds",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_hdr_bind_fail, "mdt_hdr_bind_fail",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->mdt_pld_bind_fail, "mdt_pld_bind_fail",
+ KSTAT_DATA_ULONG);
+#endif
+#ifdef ACNXGEPT_JUMBO
+ kstat_named_init(&nxgekp->tx_jumbo_pkts, "tx_jumbo_pkts",
+ KSTAT_DATA_ULONG);
+#endif
+
+ /*
+ * Rx Statistics.
+ */
+ kstat_named_init(&nxgekp->rx_inits, "rx_inits",
+ KSTAT_DATA_ULONG);
+#ifdef ACNXGEPT_JUMBO
+ kstat_named_init(&nxgekp->rx_jumbo_pkts, "rx_jumbo_pkts",
+ KSTAT_DATA_ULONG);
+#endif
+ kstat_named_init(&nxgekp->rx_hdr_pkts, "rx_hdr_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_mtu_pkts, "rx_mtu_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_split_pkts, "rx_split_pkts",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_no_buf, "rx_no_buf",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_no_comp_wb, "rx_no_comp_wb",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_ov_flow, "rx_ov_flow",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_len_mm, "rx_len_mm",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_tag_err, "rx_tag_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_nocanput, "rx_nocanput",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_msgdup_fail, "rx_msgdup_fail",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_allocb_fail, "rx_allocb_fail",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * Receive buffer management statistics.
+ */
+ kstat_named_init(&nxgekp->rx_new_pages, "rx_new_pages",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_new_hdr_pgs, "rx_new_hdr_pgs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_new_mtu_pgs, "rx_new_mtu_pgs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_new_nxt_pgs, "rx_new_nxt_pgs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_reused_pgs, "rx_reused_pgs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hdr_drops, "rx_hdr_drops",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_mtu_drops, "rx_mtu_drops",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_nxt_drops, "rx_nxt_drops",
+ KSTAT_DATA_ULONG);
+ /*
+ * Receive flow statistics
+ */
+ kstat_named_init(&nxgekp->rx_rel_flow, "rx_rel_flow",
+ KSTAT_DATA_ULONG);
+
+ kstat_named_init(&nxgekp->rx_rel_bit, "rx_rel_bit",
+ KSTAT_DATA_ULONG);
+
+ kstat_named_init(&nxgekp->rx_pkts_dropped, "rx_pkts_dropped",
+ KSTAT_DATA_ULONG);
+
+ /* General MAC statistics */
+
+ kstat_named_init(&nxgekp->ifspeed, "ifspeed",
+ KSTAT_DATA_UINT64);
+ kstat_named_init(&nxgekp->promisc, "promisc",
+ KSTAT_DATA_CHAR);
+ kstat_named_init(&nxgekp->rev_id, "rev_id",
+ KSTAT_DATA_ULONG);
+
+ /*
+ * PCI Bus statistics.
+ */
+ kstat_named_init(&nxgekp->pci_bus_speed, "pci_bus_speed",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_err, "pci_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_rta_err, "pci_rta_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_rma_err, "pci_rma_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_parity_err, "pci_parity_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_bad_ack_err, "pci_bad_ack_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_drto_err, "pci_drto_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_dmawz_err, "pci_dmawz_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->pci_dmarz_err, "pci_dmarz_err",
+ KSTAT_DATA_ULONG);
+
+ kstat_named_init(&nxgekp->rx_taskq_waits, "rx_taskq_waits",
+ KSTAT_DATA_ULONG);
+
+ ksp->ks_update = nxge_port_kstat_update;
+ ksp->ks_private = (void *) nxgep;
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC)
+ nxge_xmac_init_kstats(ksp);
+ else
+ nxge_bmac_init_kstats(ksp);
+ kstat_install(ksp);
+ nxgep->statsp->port_ksp = ksp;
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_setup_kstats"));
+}
+
+void
+nxge_xmac_init_kstats(struct kstat *ksp)
+{
+ p_nxge_xmac_kstat_t nxgekp;
+
+ nxgekp = (p_nxge_xmac_kstat_t)ksp->ks_data;
+
+ /*
+ * Transmit MAC statistics.
+ */
+ kstat_named_init(&nxgekp->tx_frame_cnt, "txmac_frame_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_underflow_err, "txmac_underflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_overflow_err, "txmac_overflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_maxpktsize_err, "txmac_maxpktsize_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_fifo_xfr_err, "txmac_fifo_xfr_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_byte_cnt, "txmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+
+ /* Receive MAC statistics */
+
+ kstat_named_init(&nxgekp->rx_overflow_err, "rxmac_overflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_underflow_err, "rxmac_underflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_crc_err_cnt, "rxmac_crc_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_len_err_cnt, "rxmac_length_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_viol_err_cnt, "rxmac_code_violations",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_byte_cnt, "rxmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_frame_align_err_cnt,
+ "rxmac_alignment_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist1_cnt, "rxmac_64_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist2_cnt, "rxmac_65_127_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist3_cnt, "rxmac_128_255_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist4_cnt, "rxmac_256_511_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist5_cnt, "rxmac_512_1023_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist6_cnt, "rxmac_1024_1522_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_broadcast_cnt, "rxmac_broadcast_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_mult_cnt, "rxmac_multicast_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_frag_cnt, "rxmac_fragment_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_linkfault_err_cnt, "rxmac_linkfault_errs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_remote_fault_err_cnt,
+ "rxmac_remote_faults",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_local_fault_err_cnt, "rxmac_local_faults",
+ KSTAT_DATA_ULONG);
+
+ /* XPCS statistics */
+
+ kstat_named_init(&nxgekp->xpcs_deskew_err_cnt, "xpcs_deskew_err_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xpcs_ln0_symbol_err_cnt,
+ "xpcs_ln0_symbol_err_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xpcs_ln1_symbol_err_cnt,
+ "xpcs_ln1_symbol_err_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xpcs_ln2_symbol_err_cnt,
+ "xpcs_ln2_symbol_err_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->xpcs_ln3_symbol_err_cnt,
+ "xpcs_ln3_symbol_err_cnt",
+ KSTAT_DATA_ULONG);
+}
+
+void
+nxge_bmac_init_kstats(struct kstat *ksp)
+{
+ p_nxge_bmac_kstat_t nxgekp;
+
+ nxgekp = (p_nxge_bmac_kstat_t)ksp->ks_data;
+
+ /*
+ * Transmit MAC statistics.
+ */
+ kstat_named_init(&nxgekp->tx_frame_cnt, "txmac_frame_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_underrun_err, "txmac_underflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_max_pkt_err, "txmac_maxpktsize_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_byte_cnt, "txmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+
+ /* Receive MAC statistics */
+
+ kstat_named_init(&nxgekp->rx_overflow_err, "rxmac_overflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_crc_err_cnt, "rxmac_crc_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_len_err_cnt, "rxmac_length_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_viol_err_cnt, "rxmac_code_violations",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_byte_cnt, "rxmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_align_err_cnt, "rxmac_alignment_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_frame_cnt, "rxmac_frame_cnt",
+ KSTAT_DATA_ULONG);
+}
+
+void
+nxge_mac_init_kstats(p_nxge_t nxgep, struct kstat *ksp)
+{
+ p_nxge_mac_kstat_t nxgekp;
+
+ nxgekp = (p_nxge_mac_kstat_t)ksp->ks_data;
+
+ /*
+ * Transmit MAC statistics.
+ */
+ kstat_named_init(&nxgekp->tx_frame_cnt, "txmac_frame_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_underflow_err, "txmac_underflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_overflow_err, "txmac_overflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_maxpktsize_err, "txmac_maxpktsize_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_fifo_xfr_err, "txmac_fifo_xfr_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->tx_byte_cnt, "txmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+
+ /* Receive MAC statistics */
+
+ kstat_named_init(&nxgekp->rx_overflow_err, "rxmac_overflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_underflow_err, "rxmac_underflow_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_crc_err_cnt, "rxmac_crc_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_len_err_cnt, "rxmac_length_err",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_viol_err_cnt, "rxmac_code_violations",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_byte_cnt, "rxmac_byte_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_frame_align_err_cnt,
+ "rxmac_alignment_err",
+ KSTAT_DATA_ULONG);
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ kstat_named_init(&nxgekp->rx_hist1_cnt, "rxmac_64_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist2_cnt, "rxmac_65_127_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist3_cnt, "rxmac_128_255_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist4_cnt, "rxmac_256_511_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist5_cnt, "rxmac_512_1023_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_hist6_cnt, "rxmac_1024_1522_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_broadcast_cnt,
+ "rxmac_broadcast_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_mult_cnt, "rxmac_multicast_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_frag_cnt, "rxmac_fragment_cnt",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_linkfault_err_cnt,
+ "rxmac_linkfault_errs",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_remote_fault_err_cnt,
+ "rxmac_remote_faults",
+ KSTAT_DATA_ULONG);
+ kstat_named_init(&nxgekp->rx_local_fault_err_cnt,
+ "rxmac_local_faults",
+ KSTAT_DATA_ULONG);
+ } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
+ kstat_named_init(&nxgekp->rx_frame_cnt, "rxmac_frame_cnt",
+ KSTAT_DATA_ULONG);
+ }
+}
+
+void
+nxge_destroy_kstats(p_nxge_t nxgep)
+{
+ int channel;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_destroy_kstats"));
+ if (nxgep->statsp == NULL) {
+ return;
+ }
+ if (nxgep->statsp->ksp) {
+ kstat_delete(nxgep->statsp->ksp);
+ }
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ for (channel = 0; channel < p_cfgp->max_rdcs; channel++) {
+ if (nxgep->statsp->rdc_ksp[channel]) {
+ kstat_delete(nxgep->statsp->rdc_ksp[channel]);
+ }
+ }
+
+
+ for (channel = 0; channel < p_cfgp->max_tdcs; channel++) {
+ if (nxgep->statsp->tdc_ksp[channel]) {
+ kstat_delete(nxgep->statsp->tdc_ksp[channel]);
+ }
+ }
+
+ if (nxgep->statsp->rdc_sys_ksp)
+ kstat_delete(nxgep->statsp->rdc_sys_ksp);
+
+ if (nxgep->statsp->fflp_ksp[0]) {
+ kstat_delete(nxgep->statsp->fflp_ksp[0]);
+ }
+
+ if (nxgep->statsp->ipp_ksp)
+ kstat_delete(nxgep->statsp->ipp_ksp);
+
+ if (nxgep->statsp->txc_ksp)
+ kstat_delete(nxgep->statsp->txc_ksp);
+
+ if (nxgep->statsp->mac_ksp)
+ kstat_delete(nxgep->statsp->mac_ksp);
+
+ if (nxgep->statsp->zcp_ksp)
+ kstat_delete(nxgep->statsp->zcp_ksp);
+
+ if (nxgep->statsp->port_ksp)
+ kstat_delete(nxgep->statsp->port_ksp);
+
+ if (nxgep->statsp->mmac_ksp)
+ kstat_delete(nxgep->statsp->mmac_ksp);
+
+ if (nxgep->statsp) {
+ KMEM_FREE(nxgep->statsp, nxgep->statsp->stats_size);
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_destroy_kstats"));
+}
+
+int
+nxge_port_kstat_update(kstat_t *ksp, int rw)
+{
+ p_nxge_t nxgep;
+ p_nxge_stats_t statsp;
+ p_nxge_port_kstat_t nxgekp;
+ int channel;
+ uint64_t b64 = 0;
+ uint64_t c64 = 0;
+ uint32_t e32;
+ nxgep = (p_nxge_t)ksp->ks_private;
+ if (nxgep == NULL)
+ return (-1);
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_port_kstat_update"));
+ statsp = (p_nxge_stats_t)nxgep->statsp;
+ nxgekp = (p_nxge_port_kstat_t)ksp->ks_data;
+ nxge_save_cntrs(nxgep);
+
+ if (rw == KSTAT_WRITE) {
+ statsp->port_stats.ipackets = nxgekp->ipackets64.value.ull;
+ statsp->port_stats.ierrors = nxgekp->ierrors.value.ul;
+ statsp->port_stats.opackets = nxgekp->opackets64.value.ull;
+ statsp->port_stats.oerrors = nxgekp->oerrors.value.ul;
+ statsp->port_stats.collisions = nxgekp->collisions.value.ull;
+
+ /*
+ * MIB II kstat variables
+ */
+ statsp->port_stats.rbytes = nxgekp->rbytes64.value.ull;
+ statsp->port_stats.obytes = nxgekp->obytes64.value.ull;
+ statsp->port_stats.multircv = nxgekp->multircv.value.ul;
+ statsp->port_stats.multixmt = nxgekp->multixmt.value.ul;
+ statsp->port_stats.brdcstrcv = nxgekp->brdcstrcv.value.ul;
+ statsp->port_stats.brdcstxmt = nxgekp->brdcstxmt.value.ul;
+ statsp->port_stats.norcvbuf = nxgekp->norcvbuf.value.ul;
+ statsp->port_stats.noxmtbuf = nxgekp->noxmtbuf.value.ul;
+
+ statsp->mac_stats.rev_id = nxgekp->rev_id.value.ul;
+
+ /*
+ * transceiver state informations.
+ */
+ statsp->mac_stats.xcvr_inits = nxgekp->xcvr_inits.value.ul;
+
+ /*
+ * Tx Statistics.
+ */
+ statsp->port_stats.tx_inits = nxgekp->tx_inits.value.ul;
+ statsp->port_stats.tx_starts = nxgekp->tx_starts.value.ul;
+ statsp->port_stats.tx_nocanput = nxgekp->tx_nocanput.value.ul;
+ statsp->port_stats.tx_msgdup_fail =
+ nxgekp->tx_msgdup_fail.value.ul;
+ statsp->port_stats.tx_allocb_fail =
+ nxgekp->tx_allocb_fail.value.ul;
+ statsp->port_stats.tx_no_desc = nxgekp->tx_no_desc.value.ul;
+ statsp->port_stats.tx_dma_bind_fail
+ = nxgekp->tx_dma_bind_fail.value.ul;
+ statsp->port_stats.tx_uflo = nxgekp->tx_uflo.value.ul;
+
+ statsp->port_stats.tx_hdr_pkts = nxgekp->tx_hdr_pkts.value.ul;
+ statsp->port_stats.tx_ddi_pkts = nxgekp->tx_ddi_pkts.value.ul;
+ statsp->port_stats.tx_dvma_pkts = nxgekp->tx_dvma_pkts.value.ul;
+
+#if defined MULTI_DATA_TX || defined MULTI_DATA_TXV2
+ statsp->port_stats.mdt_reqs = nxgekp->mdt_reqs.value.ul;
+ statsp->port_stats.mdt_hdr_bufs = nxgekp->mdt_hdr_bufs.value.ul;
+ statsp->port_stats.mdt_pld_bufs = nxgekp->mdt_pld_bufs.value.ul;
+ statsp->port_stats.mdt_pkts = nxgekp->mdt_pkts.value.ul;
+ statsp->port_stats.mdt_hdrs = nxgekp->mdt_hdrs.value.ul;
+ statsp->port_stats.mdt_plds = nxgekp->mdt_plds.value.ul;
+ statsp->port_stats.mdt_hdr_bind_fail =
+ nxgekp->mdt_hdr_bind_fail.value.ul;
+ statsp->port_stats.mdt_pld_bind_fail =
+ nxgekp->mdt_pld_bind_fail.value.ul;
+#endif
+
+#ifdef ACCEPT_JUMBO
+ statsp->port_stats.tx_jumbo_pkts =
+ nxgekp->tx_jumbo_pkts.value.ul;
+#endif
+
+ statsp->port_stats.tx_max_pend = nxgekp->tx_max_pend.value.ul;
+
+ /*
+ * Rx Statistics.
+ */
+ statsp->port_stats.rx_inits = nxgekp->rx_inits.value.ul;
+#ifdef ACNXGEPT_JUMBO
+ statsp->port_stats.rx_jumbo_pkts =
+ nxgekp->rx_jumbo_pkts.value.ul;
+#endif
+ statsp->port_stats.rx_hdr_pkts = nxgekp->rx_hdr_pkts.value.ul;
+ statsp->port_stats.rx_mtu_pkts = nxgekp->rx_mtu_pkts.value.ul;
+ statsp->port_stats.rx_split_pkts =
+ nxgekp->rx_split_pkts.value.ul;
+ statsp->port_stats.rx_no_buf = nxgekp->rx_no_buf.value.ul;
+ statsp->port_stats.rx_no_comp_wb =
+ nxgekp->rx_no_comp_wb.value.ul;
+ statsp->port_stats.rx_ov_flow = nxgekp->rx_ov_flow.value.ul;
+ statsp->port_stats.rx_len_mm = nxgekp->rx_len_mm.value.ul;
+ statsp->port_stats.rx_tag_err = nxgekp->rx_tag_err.value.ul;
+ statsp->port_stats.rx_nocanput = nxgekp->rx_nocanput.value.ul;
+ statsp->port_stats.rx_msgdup_fail =
+ nxgekp->rx_msgdup_fail.value.ul;
+ statsp->port_stats.rx_allocb_fail =
+ nxgekp->rx_allocb_fail.value.ul;
+
+ /*
+ * Receive buffer management statistics.
+ */
+ statsp->port_stats.rx_new_pages = nxgekp->rx_new_pages.value.ul;
+ statsp->port_stats.rx_new_hdr_pgs =
+ nxgekp->rx_new_hdr_pgs.value.ul;
+ statsp->port_stats.rx_new_mtu_pgs =
+ nxgekp->rx_new_mtu_pgs.value.ul;
+ statsp->port_stats.rx_new_nxt_pgs =
+ nxgekp->rx_new_nxt_pgs.value.ul;
+ statsp->port_stats.rx_reused_pgs =
+ nxgekp->rx_reused_pgs.value.ul;
+ statsp->port_stats.rx_hdr_drops = nxgekp->rx_hdr_drops.value.ul;
+ statsp->port_stats.rx_mtu_drops = nxgekp->rx_mtu_drops.value.ul;
+ statsp->port_stats.rx_nxt_drops = nxgekp->rx_nxt_drops.value.ul;
+
+ /*
+ * Receive flow statistics
+ */
+ statsp->port_stats.rx_rel_flow = nxgekp->rx_rel_flow.value.ul;
+ statsp->port_stats.rx_rel_bit = nxgekp->rx_rel_bit.value.ul;
+ statsp->port_stats.rx_pkts_dropped =
+ nxgekp->rx_pkts_dropped.value.ul;
+
+ /*
+ * PCI Bus Statistics.
+ */
+ statsp->port_stats.pci_bus_speed =
+ nxgekp->pci_bus_speed.value.ul;
+ statsp->port_stats.pci_err = nxgekp->pci_err.value.ul;
+ statsp->port_stats.pci_rta_err = nxgekp->pci_rta_err.value.ul;
+ statsp->port_stats.pci_rma_err = nxgekp->pci_rma_err.value.ul;
+ statsp->port_stats.pci_parity_err =
+ nxgekp->pci_parity_err.value.ul;
+ statsp->port_stats.pci_bad_ack_err =
+ nxgekp->pci_bad_ack_err.value.ul;
+ statsp->port_stats.pci_drto_err = nxgekp->pci_drto_err.value.ul;
+ statsp->port_stats.pci_dmawz_err =
+ nxgekp->pci_dmawz_err.value.ul;
+ statsp->port_stats.pci_dmarz_err =
+ nxgekp->pci_dmarz_err.value.ul;
+
+ statsp->port_stats.rx_taskq_waits =
+ nxgekp->rx_taskq_waits.value.ul;
+
+ (void) nxge_xmac_stat_update(ksp, KSTAT_WRITE);
+
+ return (0);
+ } else {
+ c64 = 0;
+ b64 = 0;
+ e32 = 0;
+ for (channel = 0; channel < nxgep->nrdc; channel++) {
+ c64 += nxgep->statsp->rdc_stats[channel].ipackets;
+ b64 += nxgep->statsp->rdc_stats[channel].ibytes;
+ e32 += nxgep->statsp->rdc_stats[channel].ierrors;
+ }
+ nxgekp->ipackets.value.ul = (uint32_t)c64;
+ nxgekp->ipackets64.value.ull = c64;
+ nxgekp->ierrors.value.ul = e32;
+ nxgekp->rbytes.value.ul = (uint32_t)b64;
+ nxgekp->rbytes64.value.ull = b64;
+ c64 = 0;
+ b64 = 0;
+ e32 = 0;
+ for (channel = 0; channel < nxgep->ntdc; channel++) {
+ c64 += nxgep->statsp->tdc_stats[channel].opackets;
+ b64 += nxgep->statsp->tdc_stats[channel].obytes;
+ e32 += nxgep->statsp->tdc_stats[channel].oerrors;
+ }
+
+ nxgekp->opackets.value.ul = (uint32_t)c64;
+ nxgekp->opackets64.value.ull = c64;
+ nxgekp->obytes.value.ul = (uint32_t)b64;
+ nxgekp->obytes64.value.ull = b64;
+ nxgekp->oerrors.value.ul = e32;
+
+ nxgekp->collisions.value.ull = statsp->port_stats.collisions;
+
+ /*
+ * MIB II kstat variables
+ */
+ nxgekp->multircv.value.ul = statsp->port_stats.multircv;
+ nxgekp->multixmt.value.ul = statsp->port_stats.multixmt;
+ nxgekp->brdcstrcv.value.ul = statsp->port_stats.brdcstrcv;
+ nxgekp->brdcstxmt.value.ul = statsp->port_stats.brdcstxmt;
+ nxgekp->norcvbuf.value.ul = statsp->port_stats.norcvbuf;
+ nxgekp->noxmtbuf.value.ul = statsp->port_stats.noxmtbuf;
+
+ if (nxgep->filter.all_phys_cnt)
+ (void) strcpy(nxgekp->promisc.value.c, "phys");
+ else if (nxgep->filter.all_multicast_cnt)
+ (void) strcpy(nxgekp->promisc.value.c, "multi");
+ else
+ (void) strcpy(nxgekp->promisc.value.c, "off");
+
+ nxgekp->ifspeed.value.ul
+ = statsp->mac_stats.link_speed * 1000000ULL;
+
+ nxgekp->rev_id.value.ul = statsp->mac_stats.rev_id;
+
+ /*
+ * transceiver state informations.
+ */
+ nxgekp->xcvr_inits.value.ul = statsp->mac_stats.xcvr_inits;
+ nxgekp->xcvr_inuse.value.ul = statsp->mac_stats.xcvr_inuse;
+ nxgekp->xcvr_addr.value.ul = statsp->mac_stats.xcvr_portn;
+ nxgekp->xcvr_id.value.ul = statsp->mac_stats.xcvr_id;
+ nxgekp->cap_autoneg.value.ul = statsp->mac_stats.cap_autoneg;
+ nxgekp->cap_10gfdx.value.ul = statsp->mac_stats.cap_10gfdx;
+ nxgekp->cap_10ghdx.value.ul = statsp->mac_stats.cap_10ghdx;
+ nxgekp->cap_1000fdx.value.ul = statsp->mac_stats.cap_1000fdx;
+ nxgekp->cap_1000hdx.value.ul = statsp->mac_stats.cap_1000hdx;
+ nxgekp->cap_100T4.value.ul = statsp->mac_stats.cap_100T4;
+ nxgekp->cap_100fdx.value.ul = statsp->mac_stats.cap_100fdx;
+ nxgekp->cap_100hdx.value.ul = statsp->mac_stats.cap_100hdx;
+ nxgekp->cap_10fdx.value.ul = statsp->mac_stats.cap_10fdx;
+ nxgekp->cap_10hdx.value.ul = statsp->mac_stats.cap_10hdx;
+ nxgekp->cap_asmpause.value.ul =
+ statsp->mac_stats.cap_asmpause;
+ nxgekp->cap_pause.value.ul = statsp->mac_stats.cap_pause;
+
+ /*
+ * Link partner capabilities.
+ */
+ nxgekp->lp_cap_autoneg.value.ul =
+ statsp->mac_stats.lp_cap_autoneg;
+ nxgekp->lp_cap_10gfdx.value.ul =
+ statsp->mac_stats.lp_cap_10gfdx;
+ nxgekp->lp_cap_10ghdx.value.ul =
+ statsp->mac_stats.lp_cap_10ghdx;
+ nxgekp->lp_cap_1000fdx.value.ul =
+ statsp->mac_stats.lp_cap_1000fdx;
+ nxgekp->lp_cap_1000hdx.value.ul =
+ statsp->mac_stats.lp_cap_1000hdx;
+ nxgekp->lp_cap_100T4.value.ul =
+ statsp->mac_stats.lp_cap_100T4;
+ nxgekp->lp_cap_100fdx.value.ul =
+ statsp->mac_stats.lp_cap_100fdx;
+ nxgekp->lp_cap_100hdx.value.ul =
+ statsp->mac_stats.lp_cap_100hdx;
+ nxgekp->lp_cap_10fdx.value.ul =
+ statsp->mac_stats.lp_cap_10fdx;
+ nxgekp->lp_cap_10hdx.value.ul =
+ statsp->mac_stats.lp_cap_10hdx;
+ nxgekp->lp_cap_asmpause.value.ul =
+ statsp->mac_stats.lp_cap_asmpause;
+ nxgekp->lp_cap_pause.value.ul =
+ statsp->mac_stats.lp_cap_pause;
+
+ /*
+ * Physical link statistics.
+ */
+ nxgekp->link_T4.value.ul = statsp->mac_stats.link_T4;
+ nxgekp->link_speed.value.ul = statsp->mac_stats.link_speed;
+ if (statsp->mac_stats.link_duplex == 2)
+ (void) strcpy(nxgekp->link_duplex.value.c, "full");
+ else if (statsp->mac_stats.link_duplex == 1)
+ (void) strcpy(nxgekp->link_duplex.value.c, "half");
+ else
+ (void) strcpy(nxgekp->link_duplex.value.c, "unknown");
+ nxgekp->link_asmpause.value.ul =
+ statsp->mac_stats.link_asmpause;
+ nxgekp->link_pause.value.ul = statsp->mac_stats.link_pause;
+ nxgekp->link_up.value.ul = statsp->mac_stats.link_up;
+
+ /*
+ * Lets the user know the MTU currently in use by
+ * the physical MAC port.
+ */
+ nxgekp->mac_mtu.value.ul = statsp->mac_stats.mac_mtu;
+
+ /*
+ * Loopback statistics.
+ */
+ nxgekp->lb_mode.value.ul = statsp->port_stats.lb_mode;
+
+ /*
+ * This tells the user whether the driver is in QOS mode
+ * or not.
+ */
+ nxgekp->qos_mode.value.ul = statsp->port_stats.qos_mode;
+
+ /*
+ * This tells whether the instance is trunked or not
+ */
+ nxgekp->trunk_mode.value.ul = statsp->port_stats.trunk_mode;
+
+ /*
+ * Tx Statistics.
+ */
+ nxgekp->tx_inits.value.ul = 0;
+ nxgekp->tx_starts.value.ul = 0;
+ nxgekp->tx_nocanput.value.ul = 0;
+ nxgekp->tx_msgdup_fail.value.ul = 0;
+ nxgekp->tx_allocb_fail.value.ul = 0;
+ nxgekp->tx_no_desc.value.ul = 0;
+ nxgekp->tx_dma_bind_fail.value.ul = 0;
+ nxgekp->tx_uflo.value.ul = 0;
+
+ for (channel = 0; channel < nxgep->ntdc; channel++) {
+ nxgekp->tx_inits.value.ul +=
+ statsp->tdc_stats[channel].tx_inits;
+ nxgekp->tx_starts.value.ul +=
+ statsp->tdc_stats[channel].tx_starts;
+ nxgekp->tx_nocanput.value.ul +=
+ statsp->tdc_stats[channel].tx_nocanput;
+ nxgekp->tx_msgdup_fail.value.ul +=
+ statsp->tdc_stats[channel].tx_msgdup_fail;
+ nxgekp->tx_allocb_fail.value.ul +=
+ statsp->tdc_stats[channel].tx_allocb_fail;
+ nxgekp->tx_no_desc.value.ul +=
+ statsp->tdc_stats[channel].tx_no_desc;
+ nxgekp->tx_dma_bind_fail.value.ul +=
+ statsp->tdc_stats[channel].tx_dma_bind_fail;
+ nxgekp->tx_uflo.value.ul +=
+ statsp->tdc_stats[channel].tx_uflo;
+ nxgekp->tx_hdr_pkts.value.ul +=
+ statsp->tdc_stats[channel].tx_hdr_pkts;
+ nxgekp->tx_ddi_pkts.value.ul +=
+ statsp->tdc_stats[channel].tx_ddi_pkts;
+ nxgekp->tx_dvma_pkts.value.ul +=
+ statsp->tdc_stats[channel].tx_dvma_pkts;
+ }
+
+
+
+#if defined MULTI_DATA_TX || defined MULTI_DATA_TXV2
+ nxgekp->mdt_reqs.value.ul = statsp->port_stats.mdt_reqs;
+ nxgekp->mdt_hdr_bufs.value.ul =
+ statsp->port_stats.mdt_hdr_bufs;
+ nxgekp->mdt_pld_bufs.value.ul =
+ statsp->port_stats.mdt_pld_bufs;
+ nxgekp->mdt_pkts.value.ul = statsp->port_stats.mdt_pkts;
+ nxgekp->mdt_hdrs.value.ul = statsp->port_stats.mdt_hdrs;
+ nxgekp->mdt_plds.value.ul = statsp->port_stats.mdt_plds;
+ nxgekp->mdt_hdr_bind_fail.value.ul =
+ statsp->port_stats.mdt_hdr_bind_fail;
+ nxgekp->mdt_pld_bind_fail.value.ul =
+ statsp->port_stats.mdt_pld_bind_fail;
+#endif
+#ifdef ACCEPT_JUMBO
+ nxgekp->tx_jumbo_pkts.value.ul =
+ statsp->port_stats.tx_jumbo_pkts;
+#endif
+#ifdef TX_MBLK_DEST
+ nxgekp->tx_1_desc.value.ul = statsp->port_stats.tx_1_desc;
+ nxgekp->tx_2_desc.value.ul = statsp->port_stats.tx_2_desc;
+ nxgekp->tx_3_desc.value.ul = statsp->port_stats.tx_3_desc;
+ nxgekp->tx_4_desc.value.ul = statsp->port_stats.tx_4_desc;
+ nxgekp->tx_5_desc.value.ul = statsp->port_stats.tx_5_desc;
+ nxgekp->tx_6_desc.value.ul = statsp->port_stats.tx_6_desc;
+ nxgekp->tx_7_desc.value.ul = statsp->port_stats.tx_7_desc;
+ nxgekp->tx_8_desc.value.ul = statsp->port_stats.tx_8_desc;
+ nxgekp->tx_max_desc.value.ul =
+ statsp->port_stats.tx_max_desc;
+#endif
+ nxgekp->tx_max_pend.value.ul =
+ statsp->port_stats.tx_max_pend;
+ /*
+ * Rx Statistics.
+ */
+ nxgekp->rx_inits.value.ul = statsp->port_stats.rx_inits;
+#ifdef ACCEPT_JUMBO
+ nxgekp->rx_jumbo_pkts.value.ul =
+ statsp->port_stats.rx_jumbo_pkts;
+#endif
+ nxgekp->rx_hdr_pkts.value.ul =
+ statsp->port_stats.rx_hdr_pkts;
+ nxgekp->rx_mtu_pkts.value.ul =
+ statsp->port_stats.rx_mtu_pkts;
+ nxgekp->rx_split_pkts.value.ul =
+ statsp->port_stats.rx_split_pkts;
+ nxgekp->rx_no_buf.value.ul = statsp->port_stats.rx_no_buf;
+ nxgekp->rx_no_comp_wb.value.ul =
+ statsp->port_stats.rx_no_comp_wb;
+ nxgekp->rx_ov_flow.value.ul =
+ statsp->port_stats.rx_ov_flow;
+ nxgekp->rx_len_mm.value.ul =
+ statsp->port_stats.rx_len_mm;
+ nxgekp->rx_tag_err.value.ul =
+ statsp->port_stats.rx_tag_err;
+ nxgekp->rx_nocanput.value.ul =
+ statsp->port_stats.rx_nocanput;
+ nxgekp->rx_msgdup_fail.value.ul =
+ statsp->port_stats.rx_msgdup_fail;
+ nxgekp->rx_allocb_fail.value.ul =
+ statsp->port_stats.rx_allocb_fail;
+
+ /*
+ * Receive buffer management statistics.
+ */
+ nxgekp->rx_new_pages.value.ul =
+ statsp->port_stats.rx_new_pages;
+ nxgekp->rx_new_hdr_pgs.value.ul =
+ statsp->port_stats.rx_new_hdr_pgs;
+ nxgekp->rx_new_mtu_pgs.value.ul =
+ statsp->port_stats.rx_new_mtu_pgs;
+ nxgekp->rx_new_nxt_pgs.value.ul =
+ statsp->port_stats.rx_new_nxt_pgs;
+ nxgekp->rx_reused_pgs.value.ul =
+ statsp->port_stats.rx_reused_pgs;
+ nxgekp->rx_hdr_drops.value.ul =
+ statsp->port_stats.rx_hdr_drops;
+ nxgekp->rx_mtu_drops.value.ul =
+ statsp->port_stats.rx_mtu_drops;
+ nxgekp->rx_nxt_drops.value.ul =
+ statsp->port_stats.rx_nxt_drops;
+
+ /*
+ * Receive flow statistics
+ */
+ nxgekp->rx_rel_flow.value.ul =
+ statsp->port_stats.rx_rel_flow;
+ nxgekp->rx_rel_bit.value.ul =
+ statsp->port_stats.rx_rel_bit;
+ nxgekp->rx_pkts_dropped.value.ul =
+ statsp->port_stats.rx_pkts_dropped;
+
+ /*
+ * PCI Bus Statistics.
+ */
+ nxgekp->pci_bus_speed.value.ul =
+ statsp->port_stats.pci_bus_speed;
+ nxgekp->pci_err.value.ul =
+ statsp->port_stats.pci_err;
+ nxgekp->pci_rta_err.value.ul =
+ statsp->port_stats.pci_rta_err;
+ nxgekp->pci_rma_err.value.ul =
+ statsp->port_stats.pci_rma_err;
+ nxgekp->pci_parity_err.value.ul =
+ statsp->port_stats.pci_parity_err;
+ nxgekp->pci_bad_ack_err.value.ul =
+ statsp->port_stats.pci_bad_ack_err;
+ nxgekp->pci_drto_err.value.ul =
+ statsp->port_stats.pci_drto_err;
+ nxgekp->pci_dmawz_err.value.ul =
+ statsp->port_stats.pci_dmawz_err;
+ nxgekp->pci_dmarz_err.value.ul =
+ statsp->port_stats.pci_dmarz_err;
+
+ nxgekp->rx_taskq_waits.value.ul =
+ statsp->port_stats.rx_taskq_waits;
+
+ (void) nxge_xmac_stat_update(ksp, KSTAT_READ);
+
+ }
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "<== nxge_port_kstat_update"));
+ return (0);
+}
+
+/*
+ * if this is the first init do not bother to save the
+ * counters.
+ */
+void
+nxge_save_cntrs(p_nxge_t nxgep)
+{
+ p_nxge_stats_t statsp;
+ ddi_devstate_t dev_stat;
+ uint64_t val;
+ npi_handle_t handle;
+ uint8_t portn;
+ uint8_t cnt8;
+ uint16_t cnt16;
+ uint32_t cnt32;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_save_cntrs"));
+
+ dev_stat = FM_GET_DEVSTATE(nxgep);
+ if (dev_stat < DDI_DEVSTATE_DEGRADED) {
+ goto nxge_save_cntrs_exit;
+ }
+
+ statsp = (p_nxge_stats_t)nxgep->statsp;
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ MUTEX_ENTER(&nxgep->ouraddr_lock);
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ /*
+ * Transmit MAC statistics.
+ */
+ XMAC_REG_RD(handle, portn, XTXMAC_FRM_CNT_REG, &val);
+ statsp->xmac_stats.tx_frame_cnt += (val & XTXMAC_FRM_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XTXMAC_BYTE_CNT_REG, &val);
+ statsp->xmac_stats.tx_byte_cnt += (val & XTXMAC_BYTE_CNT_MASK);
+ /*
+ * Receive XMAC statistics.
+ */
+ XMAC_REG_RD(handle, portn, XRXMAC_CRC_ER_CNT_REG, &val);
+ statsp->xmac_stats.rx_crc_err_cnt +=
+ (val & XRXMAC_CRC_ER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_MPSZER_CNT_REG, &val);
+ statsp->xmac_stats.rx_len_err_cnt +=
+ (val & XRXMAC_MPSZER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_CD_VIO_CNT_REG, &val);
+ statsp->xmac_stats.rx_viol_err_cnt +=
+ (val & XRXMAC_CD_VIO_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_BT_CNT_REG, &val);
+ statsp->xmac_stats.rx_byte_cnt += (val & XRXMAC_BT_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT1_REG, &val);
+ statsp->xmac_stats.rx_hist1_cnt +=
+ (val & XRXMAC_HIST_CNT1_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT2_REG, &val);
+ statsp->xmac_stats.rx_hist2_cnt +=
+ (val & XRXMAC_HIST_CNT2_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT3_REG, &val);
+ statsp->xmac_stats.rx_hist3_cnt +=
+ (val & XRXMAC_HIST_CNT3_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT4_REG, &val);
+ statsp->xmac_stats.rx_hist4_cnt +=
+ (val & XRXMAC_HIST_CNT4_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT5_REG, &val);
+ statsp->xmac_stats.rx_hist5_cnt +=
+ (val & XRXMAC_HIST_CNT5_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_HIST_CNT6_REG, &val);
+ statsp->xmac_stats.rx_hist6_cnt +=
+ (val & XRXMAC_HIST_CNT6_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_BC_FRM_CNT_REG, &val);
+ statsp->xmac_stats.rx_broadcast_cnt +=
+ (val & XRXMAC_BC_FRM_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_MC_FRM_CNT_REG, &val);
+ statsp->xmac_stats.rx_mult_cnt +=
+ (val & XRXMAC_MC_FRM_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_FRAG_CNT_REG, &val);
+ statsp->xmac_stats.rx_frag_cnt += (val & XRXMAC_FRAG_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XRXMAC_AL_ER_CNT_REG, &val);
+ statsp->xmac_stats.rx_frame_align_err_cnt +=
+ (val & XRXMAC_AL_ER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, XMAC_LINK_FLT_CNT_REG, &val);
+ statsp->xmac_stats.rx_linkfault_err_cnt +=
+ (val & XMAC_LINK_FLT_CNT_MASK);
+ (void) npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_DESCWERR_COUNTER, &cnt32);
+ statsp->xmac_stats.xpcs_deskew_err_cnt +=
+ (val & XMAC_XPCS_DESKEW_ERR_CNT_MASK);
+ (void) npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &cnt32);
+ statsp->xmac_stats.xpcs_ln0_symbol_err_cnt +=
+ (cnt32 & XMAC_XPCS_SYM_ERR_CNT_L0_MASK);
+ statsp->xmac_stats.xpcs_ln1_symbol_err_cnt +=
+ ((cnt32 & XMAC_XPCS_SYM_ERR_CNT_L1_MASK) >>
+ XMAC_XPCS_SYM_ERR_CNT_L1_SHIFT);
+ (void) npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &cnt32);
+ statsp->xmac_stats.xpcs_ln2_symbol_err_cnt +=
+ (cnt32 & XMAC_XPCS_SYM_ERR_CNT_L2_MASK);
+ statsp->xmac_stats.xpcs_ln3_symbol_err_cnt +=
+ ((cnt32 & XMAC_XPCS_SYM_ERR_CNT_L3_MASK) >>
+ XMAC_XPCS_SYM_ERR_CNT_L3_SHIFT);
+ } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
+ /*
+ * Transmit MAC statistics.
+ */
+ BMAC_REG_RD(handle, portn, BTXMAC_FRM_CNT_REG, &val);
+ statsp->bmac_stats.tx_frame_cnt += (val & BTXMAC_FRM_CNT_MASK);
+ XMAC_REG_RD(handle, portn, BTXMAC_BYTE_CNT_REG, &val);
+ statsp->bmac_stats.tx_byte_cnt += (val & BTXMAC_BYTE_CNT_MASK);
+
+ /*
+ * Receive MAC statistics.
+ */
+ XMAC_REG_RD(handle, portn, RXMAC_FRM_CNT_REG, &val);
+ statsp->bmac_stats.rx_frame_cnt += (val & RXMAC_FRM_CNT_MASK);
+ XMAC_REG_RD(handle, portn, BRXMAC_BYTE_CNT_REG, &val);
+ statsp->bmac_stats.rx_byte_cnt += (val & BRXMAC_BYTE_CNT_MASK);
+ XMAC_REG_RD(handle, portn, BMAC_AL_ER_CNT_REG, &val);
+ statsp->bmac_stats.rx_align_err_cnt +=
+ (val & BMAC_AL_ER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, MAC_LEN_ER_CNT_REG, &val);
+ statsp->bmac_stats.rx_len_err_cnt +=
+ (val & MAC_LEN_ER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, BMAC_CRC_ER_CNT_REG, &val);
+ statsp->bmac_stats.rx_crc_err_cnt +=
+ (val & BMAC_CRC_ER_CNT_MASK);
+ XMAC_REG_RD(handle, portn, BMAC_CD_VIO_CNT_REG, &val);
+ statsp->bmac_stats.rx_viol_err_cnt +=
+ (val & BMAC_CD_VIO_CNT_MASK);
+ }
+
+ /* Update IPP counters */
+ (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8);
+ statsp->ipp_stats.ecc_err_cnt += cnt8;
+ (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16);
+ statsp->ipp_stats.pkt_dis_cnt += cnt16;
+ (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16);
+ statsp->ipp_stats.bad_cs_cnt += cnt16;
+
+ MUTEX_EXIT(&nxgep->ouraddr_lock);
+
+nxge_save_cntrs_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_save_cntrs"));
+}
+
+int
+nxge_m_stat(void *arg, uint_t stat, uint64_t *value)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ p_nxge_stats_t statsp;
+ uint64_t val = 0;
+ int channel;
+
+ NXGE_DEBUG_MSG((nxgep, KST_CTL, "==> nxge_m_stat"));
+ statsp = (p_nxge_stats_t)nxgep->statsp;
+
+ switch (stat) {
+ case MAC_STAT_IFSPEED:
+ val = statsp->mac_stats.link_speed * 1000000ull;
+ break;
+
+ case MAC_STAT_MULTIRCV:
+ val = statsp->port_stats.multircv;
+ break;
+
+ case MAC_STAT_BRDCSTRCV:
+ val = statsp->port_stats.brdcstrcv;
+ break;
+
+ case MAC_STAT_MULTIXMT:
+ val = statsp->port_stats.multixmt;
+ break;
+
+ case MAC_STAT_BRDCSTXMT:
+ val = statsp->port_stats.brdcstxmt;
+ break;
+
+ case MAC_STAT_NORCVBUF:
+ val = statsp->port_stats.norcvbuf;
+ break;
+
+ case MAC_STAT_IERRORS:
+ case ETHER_STAT_MACRCV_ERRORS:
+ val = 0;
+ for (channel = 0; channel < nxgep->nrdc; channel++) {
+ val += statsp->rdc_stats[channel].ierrors;
+ }
+ break;
+
+ case MAC_STAT_NOXMTBUF:
+ val = statsp->port_stats.noxmtbuf;
+ break;
+
+ case MAC_STAT_OERRORS:
+ for (channel = 0; channel < nxgep->ntdc; channel++) {
+ val += statsp->tdc_stats[channel].oerrors;
+ }
+
+ break;
+
+ case MAC_STAT_COLLISIONS:
+ val = 0;
+ break;
+
+ case MAC_STAT_RBYTES:
+ for (channel = 0; channel < nxgep->nrdc; channel++) {
+ val += statsp->rdc_stats[channel].ibytes;
+ }
+ break;
+
+ case MAC_STAT_IPACKETS:
+ for (channel = 0; channel < nxgep->nrdc; channel++) {
+ val += statsp->rdc_stats[channel].ipackets;
+ }
+ break;
+
+ case MAC_STAT_OBYTES:
+ for (channel = 0; channel < nxgep->ntdc; channel++) {
+ val += statsp->tdc_stats[channel].obytes;
+ }
+ break;
+
+ case MAC_STAT_OPACKETS:
+ for (channel = 0; channel < nxgep->ntdc; channel++) {
+ val += statsp->tdc_stats[channel].opackets;
+ }
+ break;
+ case MAC_STAT_LINK_STATE:
+ val = statsp->mac_stats.link_duplex;
+ break;
+ case MAC_STAT_LINK_UP:
+ val = statsp->mac_stats.link_up;
+ break;
+ case MAC_STAT_PROMISC:
+ val = statsp->mac_stats.promisc;
+ break;
+ case ETHER_STAT_SQE_ERRORS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_ALIGN_ERRORS:
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC)
+ val = statsp->xmac_stats.rx_frame_align_err_cnt;
+ else if (nxgep->mac.porttype == PORT_TYPE_BMAC)
+ val = statsp->bmac_stats.rx_align_err_cnt;
+ else
+ val = 0;
+ break;
+
+ case ETHER_STAT_FCS_ERRORS:
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC)
+ val = statsp->xmac_stats.rx_crc_err_cnt;
+ else if (nxgep->mac.porttype == PORT_TYPE_BMAC)
+ val = statsp->bmac_stats.rx_crc_err_cnt;
+ else
+ val = 0;
+ break;
+
+ case ETHER_STAT_FIRST_COLLISIONS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_MULTI_COLLISIONS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_TX_LATE_COLLISIONS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_EX_COLLISIONS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_DEFER_XMTS:
+ val = 0;
+ break;
+
+ case ETHER_STAT_MACXMT_ERRORS:
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ val = statsp->xmac_stats.tx_underflow_err +
+ statsp->xmac_stats.tx_maxpktsize_err +
+ statsp->xmac_stats.tx_overflow_err +
+ statsp->xmac_stats.tx_fifo_xfr_err;
+ } else {
+ val = statsp->bmac_stats.tx_underrun_err +
+ statsp->bmac_stats.tx_max_pkt_err;
+ }
+ break;
+
+ case ETHER_STAT_CARRIER_ERRORS:
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ val = statsp->xmac_stats.rx_linkfault_err_cnt;
+ } else {
+ val = statsp->mac_stats.xcvr_inits +
+ statsp->mac_stats.serdes_inits;
+ }
+ break;
+
+ case ETHER_STAT_TOOLONG_ERRORS:
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ val = statsp->xmac_stats.tx_maxpktsize_err +
+ statsp->xmac_stats.rx_len_err_cnt;
+
+ } else {
+ val = statsp->bmac_stats.rx_len_err_cnt +
+ statsp->bmac_stats.tx_max_pkt_err;
+ }
+ break;
+
+
+ case ETHER_STAT_XCVR_ADDR:
+ val = statsp->mac_stats.xcvr_portn;
+ break;
+ case ETHER_STAT_XCVR_ID:
+ val = statsp->mac_stats.xcvr_id;
+ break;
+
+ case ETHER_STAT_XCVR_INUSE:
+ val = statsp->mac_stats.xcvr_inuse;
+ break;
+
+ case ETHER_STAT_CAP_1000FDX:
+ val = statsp->mac_stats.cap_1000fdx;
+ break;
+
+ case ETHER_STAT_CAP_1000HDX:
+ val = statsp->mac_stats.cap_1000hdx;
+ break;
+
+ case ETHER_STAT_CAP_100FDX:
+ val = statsp->mac_stats.cap_100fdx;
+ break;
+
+ case ETHER_STAT_CAP_100HDX:
+ val = statsp->mac_stats.cap_100hdx;
+ break;
+
+ case ETHER_STAT_CAP_10FDX:
+ val = statsp->mac_stats.cap_10fdx;
+ break;
+
+ case ETHER_STAT_CAP_10HDX:
+ val = statsp->mac_stats.cap_10hdx;
+ break;
+
+ case ETHER_STAT_CAP_ASMPAUSE:
+ val = statsp->mac_stats.cap_asmpause;
+ val = 1;
+ break;
+
+ case ETHER_STAT_CAP_PAUSE:
+ val = statsp->mac_stats.cap_pause;
+ break;
+
+ case ETHER_STAT_CAP_AUTONEG:
+ val = statsp->mac_stats.cap_autoneg;
+ break;
+
+ case ETHER_STAT_ADV_CAP_1000FDX:
+ val = statsp->mac_stats.adv_cap_1000fdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_1000HDX:
+ val = statsp->mac_stats.adv_cap_1000hdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_100FDX:
+ val = statsp->mac_stats.adv_cap_100fdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_100HDX:
+ val = statsp->mac_stats.adv_cap_100hdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_10FDX:
+ val = statsp->mac_stats.adv_cap_10fdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_10HDX:
+ val = statsp->mac_stats.adv_cap_10hdx;
+ break;
+
+ case ETHER_STAT_ADV_CAP_ASMPAUSE:
+ val = statsp->mac_stats.adv_cap_asmpause;
+ break;
+
+ case ETHER_STAT_ADV_CAP_PAUSE:
+ val = statsp->mac_stats.adv_cap_pause;
+ break;
+
+ case ETHER_STAT_ADV_CAP_AUTONEG:
+ val = statsp->mac_stats.adv_cap_autoneg;
+ break;
+
+ case ETHER_STAT_LP_CAP_1000FDX:
+ val = statsp->mac_stats.lp_cap_1000fdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_1000HDX:
+ val = statsp->mac_stats.lp_cap_1000hdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_100FDX:
+ val = statsp->mac_stats.lp_cap_100fdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_100HDX:
+ val = statsp->mac_stats.lp_cap_100hdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_10FDX:
+ val = statsp->mac_stats.lp_cap_10fdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_10HDX:
+ val = statsp->mac_stats.lp_cap_10hdx;
+ break;
+
+ case ETHER_STAT_LP_CAP_ASMPAUSE:
+ val = statsp->mac_stats.lp_cap_asmpause;
+ break;
+
+ case ETHER_STAT_LP_CAP_PAUSE:
+ val = statsp->mac_stats.lp_cap_pause;
+ break;
+
+ case ETHER_STAT_LP_CAP_AUTONEG:
+ val = statsp->mac_stats.lp_cap_autoneg;
+ break;
+
+ case ETHER_STAT_LINK_ASMPAUSE:
+ val = statsp->mac_stats.link_asmpause;
+ break;
+
+ case ETHER_STAT_LINK_PAUSE:
+ val = statsp->mac_stats.link_pause;
+ break;
+
+ case ETHER_STAT_LINK_AUTONEG:
+ val = statsp->mac_stats.cap_autoneg;
+ break;
+
+ case ETHER_STAT_LINK_DUPLEX:
+ val = statsp->mac_stats.link_duplex;
+ break;
+
+ default:
+ /*
+ * Shouldn't reach here...
+ */
+#ifdef NXGE_DEBUG
+ NXGE_ERROR_MSG((nxgep, KST_CTL,
+ "nxge_m_stat: unrecognized parameter value = 0x%x",
+ stat));
+#endif
+
+ return (ENOTSUP);
+ }
+ *value = val;
+ return (0);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_mac.c b/usr/src/uts/sun4v/io/nxge/nxge_mac.c
new file mode 100644
index 0000000000..85b1ec28ae
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_mac.c
@@ -0,0 +1,3383 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/nxge/nxge_mac.h>
+
+extern uint32_t nxge_no_link_notify;
+extern uint32_t nxge_no_msg;
+extern uint32_t nxge_lb_dbg;
+extern nxge_os_mutex_t nxge_mdio_lock;
+extern nxge_os_mutex_t nxge_mii_lock;
+extern boolean_t nxge_jumbo_enable;
+
+/*
+ * Ethernet broadcast address definition.
+ */
+static ether_addr_st etherbroadcastaddr =
+ {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
+
+nxge_status_t nxge_mac_init(p_nxge_t);
+
+/* Initialize the entire MAC and physical layer */
+
+nxge_status_t
+nxge_mac_init(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ nxge_status_t status = NXGE_OK;
+
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
+
+ nxgep->mac.portnum = portn;
+ nxgep->mac.porttype = PORT_TYPE_XMAC;
+
+ if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
+ nxgep->mac.porttype = PORT_TYPE_BMAC;
+
+ /* Initialize XIF to configure a network mode */
+ if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
+ goto fail;
+ }
+
+ if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
+ goto fail;
+ }
+
+ /* Initialize TX and RX MACs */
+ /*
+ * Always perform XIF init first, before TX and RX MAC init
+ */
+ if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
+ goto fail;
+
+ nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_mac_init: failed to initialize MAC port<%d>",
+ portn));
+ return (status);
+}
+
+/* Initialize the Ethernet Link */
+
+nxge_status_t
+nxge_link_init(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+#ifdef NXGE_DEBUG
+ uint8_t portn;
+
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
+#endif
+
+ if (nxgep->niu_type == N2_NIU) {
+ /* Workaround to get link up in both NIU ports */
+ if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
+ goto fail;
+ }
+ NXGE_DELAY(200000);
+ /* Initialize internal serdes */
+ if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
+ goto fail;
+ NXGE_DELAY(200000);
+ if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
+
+ return (NXGE_OK);
+
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_link_init: ",
+ "failed to initialize Ethernet link on port<%d>",
+ portn));
+
+ return (status);
+}
+
+
+/* Initialize the XIF sub-block within the MAC */
+
+nxge_status_t
+nxge_xif_init(p_nxge_t nxgep)
+{
+ uint32_t xif_cfg = 0;
+ npi_attr_t ap;
+ uint8_t portn;
+ nxge_port_t portt;
+ nxge_port_mode_t portmode;
+ p_nxge_stats_t statsp;
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
+
+ handle = nxgep->npi_handle;
+ portmode = nxgep->mac.portmode;
+ portt = nxgep->mac.porttype;
+ statsp = nxgep->statsp;
+
+ if (portt == PORT_TYPE_XMAC) {
+
+ /* Setup XIF Configuration for XMAC */
+
+ if ((portmode == PORT_10G_FIBER) ||
+ (portmode == PORT_10G_COPPER))
+ xif_cfg |= CFG_XMAC_XIF_LFS;
+
+ if (portmode == PORT_1G_COPPER) {
+ xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
+ }
+
+ /* Set MAC Internal Loopback if necessary */
+ if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
+ xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
+
+ if (statsp->mac_stats.link_speed == 100)
+ xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
+
+ xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
+
+ if (portmode == PORT_10G_FIBER) {
+ if (statsp->mac_stats.link_up) {
+ xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
+ } else {
+ xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
+ }
+ }
+
+ rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+
+ nxgep->mac.xif_config = xif_cfg;
+
+ /* Set Port Mode */
+ if ((portmode == PORT_10G_FIBER) ||
+ (portmode == PORT_10G_COPPER)) {
+ SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
+ MAC_XGMII_MODE, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ if (statsp->mac_stats.link_up) {
+ if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
+ goto fail;
+ } else {
+ if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
+ goto fail;
+ }
+ } else if ((portmode == PORT_1G_FIBER) ||
+ (portmode == PORT_1G_COPPER)) {
+ if (statsp->mac_stats.link_speed == 1000) {
+ SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
+ MAC_GMII_MODE, rs);
+ } else {
+ SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
+ MAC_MII_MODE, rs);
+ }
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ } else {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_xif_init: Unknown port mode (%d)"
+ " for port<%d>", portmode, portn));
+ goto fail;
+ }
+
+ } else if (portt == PORT_TYPE_BMAC) {
+
+ /* Setup XIF Configuration for BMAC */
+
+ if (portmode == PORT_1G_COPPER) {
+ if (statsp->mac_stats.link_speed == 100)
+ xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
+ }
+
+ if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
+ xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
+
+ if (statsp->mac_stats.link_speed == 1000)
+ xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
+
+ xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
+
+ rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.xif_config = xif_cfg;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_xif_init: Failed to initialize XIF port<%d>",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+/* Initialize the PCS sub-block in the MAC */
+
+nxge_status_t
+nxge_pcs_init(p_nxge_t nxgep)
+{
+ pcs_cfg_t pcs_cfg;
+ uint32_t val;
+ uint8_t portn;
+ nxge_port_mode_t portmode;
+ npi_handle_t handle;
+ p_nxge_stats_t statsp;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portmode = nxgep->mac.portmode;
+ portn = nxgep->mac.portnum;
+ statsp = nxgep->statsp;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
+
+ if (portmode == PORT_1G_FIBER) {
+ /* Initialize port's PCS */
+ pcs_cfg.value = 0;
+ pcs_cfg.bits.w0.enable = 1;
+ pcs_cfg.bits.w0.mask = 1;
+ PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
+ PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
+ if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ } else if ((portmode == PORT_10G_FIBER) ||
+ (portmode == PORT_10G_COPPER)) {
+ /* Use internal XPCS, bypass 1G PCS */
+ XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
+ val &= ~XMAC_XIF_XPCS_BYPASS;
+ XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
+
+ if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ /* Set XPCS Internal Loopback if necessary */
+ if ((rs = npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_CONTROL1, &val))
+ != NPI_SUCCESS)
+ goto fail;
+ if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
+ (statsp->port_stats.lb_mode == nxge_lb_mac1000))
+ val |= XPCS_CTRL1_LOOPBK;
+ else
+ val &= ~XPCS_CTRL1_LOOPBK;
+ if ((rs = npi_xmac_xpcs_write(handle, portn,
+ XPCS_REG_CONTROL1, val))
+ != NPI_SUCCESS)
+ goto fail;
+
+ /* Clear descw errors */
+ if ((rs = npi_xmac_xpcs_write(handle, portn,
+ XPCS_REG_DESCWERR_COUNTER, 0))
+ != NPI_SUCCESS)
+ goto fail;
+ /* Clear symbol errors */
+ if ((rs = npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
+ != NPI_SUCCESS)
+ goto fail;
+ if ((rs = npi_xmac_xpcs_read(handle, portn,
+ XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
+ != NPI_SUCCESS)
+ goto fail;
+
+ } else if (portmode == PORT_1G_COPPER) {
+ if (portn < 4) {
+ PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
+ PCS_DATAPATH_MODE_MII);
+ }
+ if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ } else {
+ goto fail;
+ }
+pass:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_pcs_init: Failed to initialize PCS port<%d>",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+/* Initialize the Internal Serdes */
+
+nxge_status_t
+nxge_serdes_init(p_nxge_t nxgep)
+{
+ p_nxge_stats_t statsp;
+#ifdef NXGE_DEBUG
+ uint8_t portn;
+#endif
+ nxge_status_t status = NXGE_OK;
+
+#ifdef NXGE_DEBUG
+ portn = nxgep->mac.portnum;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_serdes_init port<%d>", portn));
+#endif
+
+ statsp = nxgep->statsp;
+
+ if (nxgep->niu_type == N2_NIU) {
+ if (nxge_n2_serdes_init(nxgep) != NXGE_OK)
+ goto fail;
+ } else if ((nxgep->niu_type == NEPTUNE) ||
+ (nxgep->niu_type == NEPTUNE_2)) {
+ if ((status = nxge_neptune_serdes_init(nxgep))
+ != NXGE_OK)
+ goto fail;
+ } else {
+ goto fail;
+ }
+
+ statsp->mac_stats.serdes_inits++;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
+ portn));
+
+ return (NXGE_OK);
+
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_serdes_init: Failed to initialize serdes for port<%d>",
+ portn));
+
+ return (status);
+}
+
+/* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
+
+nxge_status_t
+nxge_n2_serdes_init(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ int chan;
+ esr_ti_cfgpll_l_t pll_cfg_l;
+ esr_ti_cfgrx_l_t rx_cfg_l;
+ esr_ti_cfgrx_h_t rx_cfg_h;
+ esr_ti_cfgtx_l_t tx_cfg_l;
+ esr_ti_cfgtx_h_t tx_cfg_h;
+ esr_ti_testcfg_t test_cfg;
+ nxge_status_t status = NXGE_OK;
+
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
+ portn));
+
+ tx_cfg_l.value = 0;
+ tx_cfg_h.value = 0;
+ rx_cfg_l.value = 0;
+ rx_cfg_h.value = 0;
+ pll_cfg_l.value = 0;
+ test_cfg.value = 0;
+
+ if (nxgep->mac.portmode == PORT_10G_FIBER) {
+ /* 0x0E01 */
+ tx_cfg_l.bits.entx = 1;
+ tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
+
+ /* 0x9101 */
+ rx_cfg_l.bits.enrx = 1;
+ rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
+ rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
+ rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
+
+ /* 0x0008 */
+ rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
+
+ /* Set loopback mode if necessary */
+ if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
+ tx_cfg_l.bits.entest = 1;
+ rx_cfg_l.bits.entest = 1;
+ test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_N2_DEV_ADDR,
+ ESR_N2_TEST_CFG_REG, test_cfg.value))
+ != NXGE_OK)
+ goto fail;
+ }
+
+ /* Use default PLL value */
+
+ } else if (nxgep->mac.portmode == PORT_1G_FIBER) {
+
+ /* 0x0E21 */
+ tx_cfg_l.bits.entx = 1;
+ tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
+ tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
+
+ /* 0x9121 */
+ rx_cfg_l.bits.enrx = 1;
+ rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
+ rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
+ rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
+ rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
+
+ /* 0x8 */
+ rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
+
+ /* MPY = 0x100 */
+ pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
+
+ /* Set PLL */
+ pll_cfg_l.bits.enpll = 1;
+ if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
+ ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
+ != NXGE_OK)
+ goto fail;
+ } else {
+ goto fail;
+ }
+
+ /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
+
+ NXGE_DELAY(20);
+
+ /* init TX channels */
+ for (chan = 0; chan < 4; chan++) {
+ if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
+ ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
+ != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
+ ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
+ != NXGE_OK)
+ goto fail;
+ }
+
+ /* init RX channels */
+ for (chan = 0; chan < 4; chan++) {
+ if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
+ ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
+ != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
+ ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
+ != NXGE_OK)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
+ portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
+ portn));
+
+ return (status);
+}
+
+/* Initialize Neptune Internal Serdes (Neptune only) */
+
+nxge_status_t
+nxge_neptune_serdes_init(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ uint8_t portn;
+ nxge_port_mode_t portmode;
+ int chan;
+ sr_rx_tx_ctrl_l_t rx_tx_ctrl_l;
+ sr_rx_tx_ctrl_h_t rx_tx_ctrl_h;
+ sr_glue_ctrl0_l_t glue_ctrl0_l;
+ sr_glue_ctrl0_h_t glue_ctrl0_h;
+ uint64_t val;
+ uint16_t val16l;
+ uint16_t val16h;
+ nxge_status_t status = NXGE_OK;
+
+ portn = nxgep->mac.portnum;
+
+ if ((portn != 0) && (portn != 1))
+ return (NXGE_OK);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>",
+ portn));
+
+ handle = nxgep->npi_handle;
+ portmode = nxgep->mac.portmode;
+
+ if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) {
+
+ switch (portn) {
+ case 0:
+ ESR_REG_WR(handle, ESR_0_CONTROL_REG,
+ ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
+ ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
+ (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
+
+ /* Set Serdes0 Internal Loopback if necessary */
+ if (nxgep->statsp->port_stats.lb_mode ==
+ nxge_lb_serdes10g) {
+ ESR_REG_WR(handle,
+ ESR_0_TEST_CONFIG_REG,
+ ESR_PAD_LOOPBACK_CH3 |
+ ESR_PAD_LOOPBACK_CH2 |
+ ESR_PAD_LOOPBACK_CH1 |
+ ESR_PAD_LOOPBACK_CH0);
+ } else {
+ ESR_REG_WR(handle,
+ ESR_0_TEST_CONFIG_REG, 0);
+ }
+ break;
+ case 1:
+ ESR_REG_WR(handle, ESR_1_CONTROL_REG,
+ ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
+ ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
+ (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
+ (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
+ (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
+
+ /* Set Serdes1 Internal Loopback if necessary */
+ if (nxgep->statsp->port_stats.lb_mode ==
+ nxge_lb_serdes10g) {
+ ESR_REG_WR(handle,
+ ESR_1_TEST_CONFIG_REG,
+ ESR_PAD_LOOPBACK_CH3 |
+ ESR_PAD_LOOPBACK_CH2 |
+ ESR_PAD_LOOPBACK_CH1 |
+ ESR_PAD_LOOPBACK_CH0);
+ } else {
+ ESR_REG_WR(handle,
+ ESR_1_TEST_CONFIG_REG, 0);
+ }
+ break;
+ default:
+ /* Nothing to do here */
+ goto done;
+ }
+
+ /* init TX RX channels */
+ for (chan = 0; chan < 4; chan++) {
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
+ &rx_tx_ctrl_l.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
+ &rx_tx_ctrl_h.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
+ &glue_ctrl0_l.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
+ &glue_ctrl0_h.value)) != NXGE_OK)
+ goto fail;
+ rx_tx_ctrl_l.bits.enstretch = 1;
+ rx_tx_ctrl_h.bits.vmuxlo = 2;
+ rx_tx_ctrl_h.bits.vpulselo = 2;
+ glue_ctrl0_l.bits.rxlosenable = 1;
+ glue_ctrl0_l.bits.samplerate = 0xF;
+ glue_ctrl0_l.bits.thresholdcount = 0xFF;
+ glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
+ rx_tx_ctrl_l.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
+ rx_tx_ctrl_h.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
+ glue_ctrl0_l.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
+ glue_ctrl0_h.value)) != NXGE_OK)
+ goto fail;
+ }
+
+ /* Apply Tx core reset */
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
+ (uint16_t)0)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
+ (uint16_t)0xffff)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DELAY(200);
+
+ /* Apply Rx core reset */
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
+ (uint16_t)0xffff)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DELAY(200);
+ if ((status = nxge_mdio_write(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
+ (uint16_t)0)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DELAY(200);
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
+ &val16l)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_read(nxgep, portn,
+ ESR_NEPTUNE_DEV_ADDR,
+ ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
+ &val16h)) != NXGE_OK)
+ goto fail;
+ if ((val16l != 0) || (val16h != 0)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Failed to reset port<%d> XAUI Serdes",
+ portn));
+ }
+
+ ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
+
+ if (portn == 0) {
+ if ((val & ESR_SIG_P0_BITS_MASK) !=
+ (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
+ ESR_SIG_XSERDES_RDY_P0 |
+ ESR_SIG_XDETECT_P0_CH3 |
+ ESR_SIG_XDETECT_P0_CH2 |
+ ESR_SIG_XDETECT_P0_CH1 |
+ ESR_SIG_XDETECT_P0_CH0)) {
+ goto fail;
+ }
+ } else if (portn == 1) {
+ if ((val & ESR_SIG_P1_BITS_MASK) !=
+ (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
+ ESR_SIG_XSERDES_RDY_P1 |
+ ESR_SIG_XDETECT_P1_CH3 |
+ ESR_SIG_XDETECT_P1_CH2 |
+ ESR_SIG_XDETECT_P1_CH1 |
+ ESR_SIG_XDETECT_P1_CH0)) {
+ goto fail;
+ }
+ }
+
+ } else if (portmode == PORT_1G_FIBER) {
+ ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val)
+ val &= ~ESR_PLL_CFG_FBDIV_2;
+ switch (portn) {
+ case 0:
+ val |= ESR_PLL_CFG_HALF_RATE_0;
+ break;
+ case 1:
+ val |= ESR_PLL_CFG_HALF_RATE_1;
+ break;
+ case 2:
+ val |= ESR_PLL_CFG_HALF_RATE_2;
+ break;
+ case 3:
+ val |= ESR_PLL_CFG_HALF_RATE_3;
+ break;
+ default:
+ goto fail;
+ }
+
+ ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
+ }
+
+done:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>",
+ portn));
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "nxge_neptune_serdes_init: "
+ "Failed to initialize Neptune serdes for port<%d>",
+ portn));
+
+ return (status);
+}
+
+/* Look for transceiver type */
+
+nxge_status_t
+nxge_xcvr_find(p_nxge_t nxgep)
+{
+ uint8_t portn;
+
+ portn = nxgep->mac.portnum;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn));
+
+ if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
+ return (NXGE_ERROR);
+
+ nxgep->mac.linkchkmode = LINKCHK_TIMER;
+ if (nxgep->mac.portmode == PORT_10G_FIBER) {
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ if ((nxgep->niu_type == NEPTUNE) ||
+ (nxgep->niu_type == NEPTUNE_2)) {
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM8704_NEPTUNE_PORT_ADDR_BASE + portn;
+ } else if (nxgep->niu_type == N2_NIU) {
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM8704_N2_PORT_ADDR_BASE + portn;
+ } else
+ return (NXGE_ERROR);
+ } else if (nxgep->mac.portmode == PORT_1G_COPPER) {
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ /*
+ * For Altas, Xcvr port numbers are swapped with ethernet
+ * port number. This is designed for better signal
+ * integrity in routing.
+ */
+
+ switch (portn) {
+ case 0:
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM5464_NEPTUNE_PORT_ADDR_BASE + 3;
+ break;
+ case 1:
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM5464_NEPTUNE_PORT_ADDR_BASE + 2;
+ break;
+ case 2:
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM5464_NEPTUNE_PORT_ADDR_BASE + 1;
+ break;
+ case 3:
+ nxgep->statsp->mac_stats.xcvr_portn =
+ BCM5464_NEPTUNE_PORT_ADDR_BASE;
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+ } else if (nxgep->mac.portmode == PORT_1G_FIBER) {
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ nxgep->statsp->mac_stats.xcvr_portn = portn;
+ } else {
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
+ nxgep->statsp->mac_stats.xcvr_inuse));
+ return (NXGE_OK);
+}
+
+/* Initialize transceiver */
+
+nxge_status_t
+nxge_xcvr_init(p_nxge_t nxgep)
+{
+ p_nxge_param_t param_arr;
+ p_nxge_stats_t statsp;
+ uint8_t portn;
+ uint16_t val;
+#ifdef NXGE_DEBUG
+ uint16_t val1;
+#endif
+ uint8_t phy_port_addr;
+ pmd_tx_control_t tx_ctl;
+ control_t ctl;
+ phyxs_control_t phyxs_ctl;
+ pcs_control_t pcs_ctl;
+ uint32_t delay = 0;
+ optics_dcntr_t op_ctr;
+ nxge_status_t status = NXGE_OK;
+
+ portn = nxgep->mac.portnum;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
+
+ param_arr = nxgep->param_arr;
+ statsp = nxgep->statsp;
+
+ /*
+ * Initialise the xcvr statistics.
+ */
+ statsp->mac_stats.cap_autoneg = 0;
+ statsp->mac_stats.cap_100T4 = 0;
+ statsp->mac_stats.cap_100fdx = 0;
+ statsp->mac_stats.cap_100hdx = 0;
+ statsp->mac_stats.cap_10fdx = 0;
+ statsp->mac_stats.cap_10hdx = 0;
+ statsp->mac_stats.cap_asmpause = 0;
+ statsp->mac_stats.cap_pause = 0;
+ statsp->mac_stats.cap_1000fdx = 0;
+ statsp->mac_stats.cap_1000hdx = 0;
+ statsp->mac_stats.cap_10gfdx = 0;
+ statsp->mac_stats.cap_10ghdx = 0;
+
+ /*
+ * Initialize the link statistics.
+ */
+ statsp->mac_stats.link_T4 = 0;
+ statsp->mac_stats.link_asmpause = 0;
+ statsp->mac_stats.link_pause = 0;
+
+ phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
+
+ switch (nxgep->mac.portmode) {
+ case PORT_10G_FIBER:
+ /* Disable Link LEDs */
+ if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
+ goto fail;
+
+ /* Set Clause 45 */
+ npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
+
+ /* Reset the transceiver */
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_PHYXS_ADDR,
+ BCM8704_PHYXS_CONTROL_REG,
+ &phyxs_ctl.value)) != NXGE_OK)
+ goto fail;
+
+ phyxs_ctl.bits.reset = 1;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_PHYXS_ADDR,
+ BCM8704_PHYXS_CONTROL_REG,
+ phyxs_ctl.value)) != NXGE_OK)
+ goto fail;
+
+ do {
+ drv_usecwait(500);
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_PHYXS_ADDR,
+ BCM8704_PHYXS_CONTROL_REG,
+ &phyxs_ctl.value)) != NXGE_OK)
+ goto fail;
+ delay++;
+ } while ((phyxs_ctl.bits.reset) && (delay < 100));
+ if (delay == 100) {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_xcvr_init: "
+ "failed to reset Transceiver on port<%d>",
+ portn));
+ status = NXGE_ERROR;
+ goto fail;
+ }
+
+ /* Set to 0x7FBF */
+ ctl.value = 0;
+ ctl.bits.res1 = 0x3F;
+ ctl.bits.optxon_lvl = 1;
+ ctl.bits.oprxflt_lvl = 1;
+ ctl.bits.optrxlos_lvl = 1;
+ ctl.bits.optxflt_lvl = 1;
+ ctl.bits.opprflt_lvl = 1;
+ ctl.bits.obtmpflt_lvl = 1;
+ ctl.bits.opbiasflt_lvl = 1;
+ ctl.bits.optxrst_lvl = 1;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_CONTROL_REG, ctl.value))
+ != NXGE_OK)
+ goto fail;
+
+ /* Set to 0x164 */
+ tx_ctl.value = 0;
+ tx_ctl.bits.tsck_lpwren = 1;
+ tx_ctl.bits.tx_dac_txck = 0x2;
+ tx_ctl.bits.tx_dac_txd = 0x1;
+ tx_ctl.bits.xfp_clken = 1;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value))
+ != NXGE_OK)
+ goto fail;
+ /*
+ * According to Broadcom's instruction, SW needs to read
+ * back these registers twice after written.
+ */
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_CONTROL_REG, &val))
+ != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_CONTROL_REG, &val))
+ != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_PMD_TX_CONTROL_REG, &val))
+ != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_PMD_TX_CONTROL_REG, &val))
+ != NXGE_OK)
+ goto fail;
+
+
+ if (((nxgep->board_ver < 4) && (portn == 1)) &&
+ ((nxgep->niu_type == NEPTUNE) ||
+ (nxgep->niu_type == NEPTUNE_2))) {
+ /*
+ * XAUI signals' polarity on Channel 0 to 2 are swapped
+ * on port 1 due to routing.
+ */
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV4_ADDR,
+ BCM8704_USER_RX2_CONTROL1_REG,
+ BCM8704_RXPOL_FLIP)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV4_ADDR,
+ BCM8704_USER_RX1_CONTROL1_REG,
+ BCM8704_RXPOL_FLIP)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV4_ADDR,
+ BCM8704_USER_RX0_CONTROL1_REG,
+ BCM8704_RXPOL_FLIP)) != NXGE_OK)
+ goto fail;
+ }
+
+ /* Enable Tx and Rx LEDs to be driven by traffic */
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
+ &op_ctr.value)) != NXGE_OK)
+ goto fail;
+ op_ctr.bits.gpio_sel = 0x3;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
+ op_ctr.value)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DELAY(1000000);
+
+ /* Set BCM8704 Internal Loopback mode if necessary */
+ if ((status = nxge_mdio_read(nxgep,
+ phy_port_addr,
+ BCM8704_PCS_DEV_ADDR,
+ BCM8704_PCS_CONTROL_REG,
+ &pcs_ctl.value)) != NXGE_OK)
+ goto fail;
+ if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
+ pcs_ctl.bits.loopback = 1;
+ else
+ pcs_ctl.bits.loopback = 0;
+ if ((status = nxge_mdio_write(nxgep,
+ phy_port_addr,
+ BCM8704_PCS_DEV_ADDR,
+ BCM8704_PCS_CONTROL_REG,
+ pcs_ctl.value)) != NXGE_OK)
+ goto fail;
+
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ 0x1, 0xA, &val);
+ if (status != NXGE_OK)
+ goto fail;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n",
+ portn, val));
+ status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
+ if (status != NXGE_OK)
+ goto fail;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n",
+ portn, val));
+ status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
+ if (status != NXGE_OK)
+ goto fail;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n",
+ portn, val));
+
+#ifdef NXGE_DEBUG
+ /* Diagnose link issue if link is not up */
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_ANALOG_STATUS0_REG,
+ &val);
+ if (status != NXGE_OK)
+ goto fail;
+
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_ANALOG_STATUS0_REG,
+ &val);
+ if (status != NXGE_OK)
+ goto fail;
+
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_TX_ALARM_STATUS_REG,
+ &val1);
+ if (status != NXGE_OK)
+ goto fail;
+
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_TX_ALARM_STATUS_REG,
+ &val1);
+ if (status != NXGE_OK)
+ goto fail;
+
+ if (val != 0x3FC) {
+ if ((val == 0x43BC) && (val1 != 0)) {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Cable not connected to peer or bad"
+ " cable on port<%d>\n", portn));
+ } else if (val == 0x639C) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Optical module (XFP) is bad or absence"
+ " on port<%d>\n", portn));
+ }
+ }
+#endif
+
+ statsp->mac_stats.cap_10gfdx = 1;
+ statsp->mac_stats.lp_cap_10gfdx = 1;
+ break;
+ case PORT_10G_COPPER:
+ break;
+ case PORT_1G_FIBER:
+ case PORT_1G_COPPER:
+ /* Set Clause 22 */
+ npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
+
+ /* Set capability flags */
+ statsp->mac_stats.cap_1000fdx =
+ param_arr[param_anar_1000fdx].value;
+ statsp->mac_stats.cap_100fdx =
+ param_arr[param_anar_100fdx].value;
+ statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
+
+ if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK)
+ goto fail;
+ break;
+ default:
+ goto fail;
+ }
+
+ statsp->mac_stats.xcvr_inits++;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
+ return (NXGE_OK);
+
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
+ portn));
+ return (status);
+}
+
+
+/* Initialize the TxMAC sub-block */
+
+nxge_status_t
+nxge_tx_mac_init(p_nxge_t nxgep)
+{
+ npi_attr_t ap;
+ uint8_t portn;
+ nxge_port_mode_t portmode;
+ nxge_port_t portt;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+ portt = nxgep->mac.porttype;
+ handle = nxgep->npi_handle;
+ portmode = nxgep->mac.portmode;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
+ portn));
+
+ /* Set Max and Min Frame Size */
+ if (nxge_jumbo_enable) {
+ SET_MAC_ATTR2(handle, ap, portn,
+ MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
+ } else {
+ SET_MAC_ATTR2(handle, ap, portn,
+ MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
+ }
+
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.is_jumbo = B_FALSE;
+ if (nxgep->mac.is_jumbo == B_TRUE)
+ nxgep->mac.maxframesize = 0x2400;
+ else
+ nxgep->mac.maxframesize = 0x5EE + 4;
+ nxgep->mac.minframesize = 64;
+
+ if (portt == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
+ 0)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
+ if ((portmode == PORT_10G_FIBER) ||
+ (portmode == PORT_10G_COPPER)) {
+ SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
+ XGMII_IPG_12_15, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.ipg[0] = XGMII_IPG_12_15;
+ } else {
+ SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
+ MII_GMII_IPG_12, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.ipg[0] = MII_GMII_IPG_12;
+ }
+ if ((rs = npi_xmac_tx_config(handle, INIT, portn,
+ CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
+ nxgep->mac.maxburstsize = 0; /* not programmable */
+ nxgep->mac.ctrltype = 0; /* not programmable */
+ nxgep->mac.pa_size = 0; /* not programmable */
+
+ if ((rs = npi_xmac_zap_tx_counters(handle, portn))
+ != NPI_SUCCESS)
+ goto fail;
+
+ } else {
+ if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
+ 0)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
+
+ SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
+ rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.ctrltype = 0x8808;
+
+ SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.pa_size = 0x7;
+
+ if ((rs = npi_bmac_tx_config(handle, INIT, portn,
+ CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
+ portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
+ portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Initialize the RxMAC sub-block */
+
+nxge_status_t
+nxge_rx_mac_init(p_nxge_t nxgep)
+{
+ npi_attr_t ap;
+ uint32_t i;
+ uint16_t hashtab_e;
+ p_hash_filter_t hash_filter;
+ npi_mac_addr_t altmac_e;
+ nxge_port_t portt;
+ uint8_t portn;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ uint16_t *addr16p;
+ uint16_t addr0, addr1, addr2;
+ xmac_rx_config_t xconfig;
+ bmac_rx_config_t bconfig;
+
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
+ portn));
+ handle = nxgep->npi_handle;
+ portt = nxgep->mac.porttype;
+
+ addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
+ addr0 = ntohs(addr16p[2]);
+ addr1 = ntohs(addr16p[1]);
+ addr2 = ntohs(addr16p[0]);
+ SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
+ rs);
+
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+ SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
+ if (rs != NPI_SUCCESS)
+ goto fail;
+
+ /*
+ * Load the multicast hash filter bits.
+ */
+ hash_filter = nxgep->hash_filter;
+ for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
+ if (hash_filter != NULL) {
+ hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
+ (NMCFILTER_REGS - 1) - i];
+ } else {
+ hashtab_e = 0;
+ }
+
+ if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
+ (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ if (portt == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
+ 0)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
+
+ altmac_e.w0 = 0;
+ altmac_e.w1 = 0;
+ altmac_e.w2 = 0;
+ for (i = 0; i < XMAC_MAX_ALT_ADDR_ENTRY; i++) {
+ if ((rs = npi_mac_altaddr_entry(handle, OP_SET, portn,
+ i, (npi_mac_addr_t *)&altmac_e)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ (void) nxge_fflp_init_hostinfo(nxgep);
+
+ xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
+ CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK |
+ CFG_XMAC_RX_STRIP_CRC;
+
+ if (nxgep->filter.all_phys_cnt != 0)
+ xconfig |= CFG_XMAC_RX_PROMISCUOUS;
+
+ if (nxgep->filter.all_multicast_cnt != 0)
+ xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
+
+ xconfig |= CFG_XMAC_RX_HASH_FILTER;
+
+ if ((rs = npi_xmac_rx_config(handle, INIT, portn,
+ xconfig)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.rx_config = xconfig;
+
+ /* Comparison of mac unique address is always enabled on XMAC */
+
+ if ((rs = npi_xmac_zap_rx_counters(handle, portn))
+ != NPI_SUCCESS)
+ goto fail;
+ } else {
+ altmac_e.w0 = 0;
+ altmac_e.w1 = 0;
+ altmac_e.w2 = 0;
+ for (i = 0; i < BMAC_MAX_ALT_ADDR_ENTRY; i++) {
+ if ((rs = npi_mac_altaddr_entry(handle, OP_SET, portn,
+ i, (npi_mac_addr_t *)&altmac_e)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ (void) nxge_fflp_init_hostinfo(nxgep);
+
+ if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
+ 0) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
+
+ bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX |
+ CFG_BMAC_RX_STRIP_CRC;
+
+ if (nxgep->filter.all_phys_cnt != 0)
+ bconfig |= CFG_BMAC_RX_PROMISCUOUS;
+
+ if (nxgep->filter.all_multicast_cnt != 0)
+ bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
+
+ bconfig |= CFG_BMAC_RX_HASH_FILTER;
+ if ((rs = npi_bmac_rx_config(handle, INIT, portn,
+ bconfig)) != NPI_SUCCESS)
+ goto fail;
+ nxgep->mac.rx_config = bconfig;
+
+ /* Always enable comparison of mac unique address */
+ if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
+ != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
+ portn));
+
+ return (NXGE_OK);
+
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
+ portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Enable TXMAC */
+
+nxge_status_t
+nxge_tx_mac_enable(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
+ nxgep->mac.portnum));
+
+ if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ /* based on speed */
+ nxgep->msg_min = ETHERMIN;
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
+ CFG_XMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
+ CFG_BMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
+ nxgep->mac.portnum));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
+ nxgep->mac.portnum));
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ else
+ return (status);
+}
+
+/* Disable TXMAC */
+
+nxge_status_t
+nxge_tx_mac_disable(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
+ nxgep->mac.portnum));
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_tx_config(handle, DISABLE,
+ nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_tx_config(handle, DISABLE,
+ nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
+ nxgep->mac.portnum));
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
+ nxgep->mac.portnum));
+ return (NXGE_ERROR | rs);
+}
+
+/* Enable RXMAC */
+
+nxge_status_t
+nxge_rx_mac_enable(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ uint8_t portn;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
+ portn));
+
+ if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
+ CFG_XMAC_RX)) != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
+ CFG_BMAC_RX)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
+ portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
+ portn));
+
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ else
+ return (status);
+}
+
+/* Disable RXMAC */
+
+nxge_status_t
+nxge_rx_mac_disable(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ uint8_t portn;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
+ portn));
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
+ CFG_XMAC_RX)) != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
+ CFG_BMAC_RX)) != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
+ portn));
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxgep_rx_mac_disable: ",
+ "Failed to disable port<%d> RxMAC",
+ portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Reset TXMAC */
+
+nxge_status_t
+nxge_tx_mac_reset(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ uint8_t portn;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
+ portn));
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
+ != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
+ != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
+ portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
+ portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Reset RXMAC */
+
+nxge_status_t
+nxge_rx_mac_reset(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ uint8_t portn;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
+ portn));
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
+ != NPI_SUCCESS)
+ goto fail;
+ } else {
+ if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
+ != NPI_SUCCESS)
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
+ portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+
+/* Enable/Disable MII Link Status change interrupt */
+
+nxge_status_t
+nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
+{
+ uint8_t portn;
+ nxge_port_mode_t portmode;
+ npi_status_t rs = NPI_SUCCESS;
+
+ portn = nxgep->mac.portnum;
+ portmode = nxgep->mac.portmode;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
+
+ if (enable == LINK_INTR_START) {
+ if (portmode == PORT_10G_FIBER) {
+ if ((rs = npi_xmac_xpcs_link_intr_enable(
+ nxgep->npi_handle,
+ portn)) != NPI_SUCCESS)
+ goto fail;
+ } else if (portmode == PORT_1G_FIBER) {
+ if ((rs = npi_mac_pcs_link_intr_enable(
+ nxgep->npi_handle,
+ portn)) != NPI_SUCCESS)
+ goto fail;
+ } else if (portmode == PORT_1G_COPPER) {
+ if ((rs = npi_mac_mif_link_intr_enable(
+ nxgep->npi_handle,
+ portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS)
+ goto fail;
+ } else
+ goto fail;
+ } else if (enable == LINK_INTR_STOP) {
+ if (portmode == PORT_10G_FIBER) {
+ if ((rs = npi_xmac_xpcs_link_intr_disable(
+ nxgep->npi_handle,
+ portn)) != NPI_SUCCESS)
+ goto fail;
+ } else if (portmode == PORT_1G_FIBER) {
+ if ((rs = npi_mac_pcs_link_intr_disable(
+ nxgep->npi_handle,
+ portn)) != NPI_SUCCESS)
+ goto fail;
+ } else if (portmode == PORT_1G_COPPER) {
+ if ((rs = npi_mac_mif_link_intr_disable(
+ nxgep->npi_handle,
+ portn)) != NPI_SUCCESS)
+ goto fail;
+ } else
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_link_intr: Failed to set port<%d> mif intr mode",
+ portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Initialize 1G Fiber / Copper transceiver using Clause 22 */
+
+nxge_status_t
+nxge_mii_xcvr_init(p_nxge_t nxgep)
+{
+ p_nxge_param_t param_arr;
+ p_nxge_stats_t statsp;
+ uint8_t xcvr_portn;
+ p_mii_regs_t mii_regs;
+ mii_bmcr_t bmcr;
+ mii_bmsr_t bmsr;
+ mii_anar_t anar;
+ mii_gcr_t gcr;
+ mii_esr_t esr;
+ mii_aux_ctl_t bcm5464r_aux;
+ int status = NXGE_OK;
+
+ uint_t delay;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
+
+ param_arr = nxgep->param_arr;
+ statsp = nxgep->statsp;
+ xcvr_portn = statsp->mac_stats.xcvr_portn;
+
+ mii_regs = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
+
+ /*
+ * Reset the transceiver.
+ */
+ delay = 0;
+ bmcr.value = 0;
+ bmcr.bits.reset = 1;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
+ goto fail;
+ do {
+ drv_usecwait(500);
+ if ((status = nxge_mii_read(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
+ != NXGE_OK)
+ goto fail;
+ delay++;
+ } while ((bmcr.bits.reset) && (delay < 1000));
+ if (delay == 1000) {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
+ goto fail;
+ }
+
+ if ((status = nxge_mii_read(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmsr),
+ &bmsr.value)) != NXGE_OK)
+ goto fail;
+
+ param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
+ param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
+ param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
+ param_arr[param_anar_100hdx].value = 0;
+ param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
+ param_arr[param_anar_10hdx].value = 0;
+
+ /*
+ * Initialise the xcvr statistics.
+ */
+ statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
+ statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
+ statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
+ statsp->mac_stats.cap_100hdx = 0;
+ statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
+ statsp->mac_stats.cap_10hdx = 0;
+ statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
+ statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
+
+ /*
+ * Initialise the xcvr advertised capability statistics.
+ */
+ statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
+ statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
+ statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
+ statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
+ statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
+ statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
+ statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
+ statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
+ statsp->mac_stats.adv_cap_asmpause =
+ param_arr[param_anar_asmpause].value;
+ statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
+
+
+ /*
+ * Check for extended status just in case we're
+ * running a Gigibit phy.
+ */
+ if (bmsr.bits.extend_status) {
+ if ((status = nxge_mii_read(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
+ != NXGE_OK)
+ goto fail;
+ param_arr[param_anar_1000fdx].value &=
+ esr.bits.link_1000fdx;
+ param_arr[param_anar_1000hdx].value = 0;
+
+ statsp->mac_stats.cap_1000fdx =
+ (esr.bits.link_1000Xfdx ||
+ esr.bits.link_1000fdx);
+ statsp->mac_stats.cap_1000hdx = 0;
+ } else {
+ param_arr[param_anar_1000fdx].value = 0;
+ param_arr[param_anar_1000hdx].value = 0;
+ }
+
+ /*
+ * Initialize 1G Statistics once the capability is established.
+ */
+ statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
+ statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
+
+ /*
+ * Initialise the link statistics.
+ */
+ statsp->mac_stats.link_T4 = 0;
+ statsp->mac_stats.link_asmpause = 0;
+ statsp->mac_stats.link_pause = 0;
+ statsp->mac_stats.link_speed = 0;
+ statsp->mac_stats.link_duplex = 0;
+ statsp->mac_stats.link_up = 0;
+
+ /*
+ * Switch off Auto-negotiation, 100M and full duplex.
+ */
+ bmcr.value = 0;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
+ goto fail;
+
+ if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
+ (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
+ bmcr.bits.loopback = 1;
+ bmcr.bits.enable_autoneg = 0;
+ if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
+ bmcr.bits.speed_1000_sel = 1;
+ bmcr.bits.duplex_mode = 1;
+ param_arr[param_autoneg].value = 0;
+ } else {
+ bmcr.bits.loopback = 0;
+ }
+
+ if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
+ (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
+ (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
+ param_arr[param_autoneg].value = 0;
+ bcm5464r_aux.value = 0;
+ bcm5464r_aux.bits.ext_lb = 1;
+ bcm5464r_aux.bits.write_1 = 1;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ BCM5464R_AUX_CTL, bcm5464r_aux.value))
+ != NXGE_OK)
+ goto fail;
+ }
+
+ if (param_arr[param_autoneg].value) {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Restarting Auto-negotiation."));
+ /*
+ * Setup our Auto-negotiation advertisement register.
+ */
+ anar.value = 0;
+ anar.bits.selector = 1;
+ anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
+ anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
+ anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
+ anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
+ anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
+ anar.bits.cap_asmpause = 0;
+ anar.bits.cap_pause = 0;
+ if (param_arr[param_anar_1000fdx].value ||
+ param_arr[param_anar_100fdx].value ||
+ param_arr[param_anar_10fdx].value) {
+ anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
+ anar.bits.cap_pause = statsp->mac_stats.cap_pause;
+ }
+
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
+ != NXGE_OK)
+ goto fail;
+ if (bmsr.bits.extend_status) {
+ gcr.value = 0;
+ gcr.bits.ms_mode_en =
+ param_arr[param_master_cfg_enable].value;
+ gcr.bits.master =
+ param_arr[param_master_cfg_value].value;
+ gcr.bits.link_1000fdx =
+ param_arr[param_anar_1000fdx].value;
+ gcr.bits.link_1000hdx =
+ param_arr[param_anar_1000hdx].value;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
+ != NXGE_OK)
+ goto fail;
+ }
+
+ bmcr.bits.enable_autoneg = 1;
+ bmcr.bits.restart_autoneg = 1;
+
+ } else {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
+ bmcr.bits.speed_1000_sel =
+ param_arr[param_anar_1000fdx].value |
+ param_arr[param_anar_1000hdx].value;
+ bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
+ (param_arr[param_anar_100fdx].value |
+ param_arr[param_anar_100hdx].value);
+ if (bmcr.bits.speed_1000_sel) {
+ statsp->mac_stats.link_speed = 1000;
+ gcr.value = 0;
+ gcr.bits.ms_mode_en =
+ param_arr[param_master_cfg_enable].value;
+ gcr.bits.master =
+ param_arr[param_master_cfg_value].value;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->gcr),
+ gcr.value))
+ != NXGE_OK)
+ goto fail;
+ if (param_arr[param_anar_1000fdx].value) {
+ bmcr.bits.duplex_mode = 1;
+ statsp->mac_stats.link_duplex = 2;
+ } else
+ statsp->mac_stats.link_duplex = 1;
+ } else if (bmcr.bits.speed_sel) {
+ statsp->mac_stats.link_speed = 100;
+ if (param_arr[param_anar_100fdx].value) {
+ bmcr.bits.duplex_mode = 1;
+ statsp->mac_stats.link_duplex = 2;
+ } else
+ statsp->mac_stats.link_duplex = 1;
+ } else {
+ statsp->mac_stats.link_speed = 10;
+ if (param_arr[param_anar_10fdx].value) {
+ bmcr.bits.duplex_mode = 1;
+ statsp->mac_stats.link_duplex = 2;
+ } else
+ statsp->mac_stats.link_duplex = 1;
+ }
+ if (statsp->mac_stats.link_duplex != 1) {
+ statsp->mac_stats.link_asmpause =
+ statsp->mac_stats.cap_asmpause;
+ statsp->mac_stats.link_pause =
+ statsp->mac_stats.cap_pause;
+ }
+
+ if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
+ (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
+ (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
+ if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
+ /* BCM5464R 1000mbps external loopback mode */
+ gcr.value = 0;
+ gcr.bits.ms_mode_en = 1;
+ gcr.bits.master = 1;
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->gcr),
+ gcr.value))
+ != NXGE_OK)
+ goto fail;
+ bmcr.value = 0;
+ bmcr.bits.speed_1000_sel = 1;
+ statsp->mac_stats.link_speed = 1000;
+ } else if (statsp->port_stats.lb_mode
+ == nxge_lb_ext100) {
+ /* BCM5464R 100mbps external loopback mode */
+ bmcr.value = 0;
+ bmcr.bits.speed_sel = 1;
+ bmcr.bits.duplex_mode = 1;
+ statsp->mac_stats.link_speed = 100;
+ } else if (statsp->port_stats.lb_mode
+ == nxge_lb_ext10) {
+ /* BCM5464R 10mbps external loopback mode */
+ bmcr.value = 0;
+ bmcr.bits.duplex_mode = 1;
+ statsp->mac_stats.link_speed = 10;
+ }
+ }
+ }
+
+ if ((status = nxge_mii_write(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmcr),
+ bmcr.value)) != NXGE_OK)
+ goto fail;
+
+ if ((status = nxge_mii_read(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
+ goto fail;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
+
+ /*
+ * Initialize the xcvr status kept in the context structure.
+ */
+ nxgep->soft_bmsr.value = 0;
+
+ if ((status = nxge_mii_read(nxgep, xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmsr),
+ &nxgep->bmsr.value)) != NXGE_OK)
+ goto fail;
+
+ statsp->mac_stats.xcvr_inits++;
+ nxgep->bmsr.value = 0;
+
+fail:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "<== nxge_mii_xcvr_init status 0x%x", status));
+ return (status);
+}
+
+/* Read from a MII compliant register */
+
+nxge_status_t
+nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
+ uint16_t *value)
+{
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
+ "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
+
+ MUTEX_ENTER(&nxge_mii_lock);
+
+ if (nxgep->mac.portmode == PORT_1G_COPPER) {
+ if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
+ xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+ } else if (nxgep->mac.portmode == PORT_1G_FIBER) {
+ if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
+ xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+ } else
+ goto fail;
+
+ MUTEX_EXIT(&nxge_mii_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
+ "xcvr_reg<%d> value=0x%x",
+ xcvr_portn, xcvr_reg, *value));
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&nxge_mii_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_mii_read: Failed to read mii on xcvr %d",
+ xcvr_portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Write to a MII compliant Register */
+
+nxge_status_t
+nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
+ uint16_t value)
+{
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
+ "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
+ value));
+
+ MUTEX_ENTER(&nxge_mii_lock);
+
+ if (nxgep->mac.portmode == PORT_1G_COPPER) {
+ if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
+ xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+ } else if (nxgep->mac.portmode == PORT_1G_FIBER) {
+ if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
+ xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+ } else
+ goto fail;
+
+ MUTEX_EXIT(&nxge_mii_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
+ "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&nxge_mii_lock);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_mii_write: Failed to write mii on xcvr %d",
+ xcvr_portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Perform read from Clause45 serdes / transceiver device */
+
+nxge_status_t
+nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
+ uint16_t xcvr_reg, uint16_t *value)
+{
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
+ xcvr_portn));
+
+ MUTEX_ENTER(&nxge_mdio_lock);
+
+ if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
+ xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+
+ MUTEX_EXIT(&nxge_mdio_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
+ xcvr_portn));
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&nxge_mdio_lock);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_mdio_read: Failed to read mdio on xcvr %d",
+ xcvr_portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+/* Perform write to Clause45 serdes / transceiver device */
+
+nxge_status_t
+nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
+ uint16_t xcvr_reg, uint16_t value)
+{
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
+ xcvr_portn));
+
+ MUTEX_ENTER(&nxge_mdio_lock);
+
+ if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
+ xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
+ goto fail;
+
+ MUTEX_EXIT(&nxge_mdio_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
+ xcvr_portn));
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&nxge_mdio_lock);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_mdio_write: Failed to write mdio on xcvr %d",
+ xcvr_portn));
+
+ return (NXGE_ERROR | rs);
+}
+
+
+/* Check MII to see if there is any link status change */
+
+nxge_status_t
+nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints)
+{
+ p_nxge_param_t param_arr;
+ p_nxge_stats_t statsp;
+ p_mii_regs_t mii_regs;
+ p_mii_bmsr_t soft_bmsr;
+ mii_anar_t anar;
+ mii_anlpar_t anlpar;
+ mii_anar_t an_common;
+ mii_aner_t aner;
+ mii_gsr_t gsr;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
+
+ mii_regs = NULL;
+ param_arr = nxgep->param_arr;
+ statsp = nxgep->statsp;
+ soft_bmsr = &nxgep->soft_bmsr;
+
+ if (bmsr_ints.bits.link_status) {
+ if (bmsr.bits.link_status) {
+ soft_bmsr->bits.link_status = 1;
+ } else {
+ statsp->mac_stats.link_up = 0;
+ soft_bmsr->bits.link_status = 0;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Link down cable problem"));
+ nxge_link_is_down(nxgep);
+ }
+ }
+
+ if (param_arr[param_autoneg].value) {
+ if (bmsr_ints.bits.auto_neg_complete) {
+ if (bmsr.bits.auto_neg_complete)
+ soft_bmsr->bits.auto_neg_complete = 1;
+ else
+ soft_bmsr->bits.auto_neg_complete = 0;
+ }
+ if (soft_bmsr->bits.link_status == 0) {
+ statsp->mac_stats.link_T4 = 0;
+ statsp->mac_stats.link_speed = 0;
+ statsp->mac_stats.link_duplex = 0;
+ statsp->mac_stats.link_asmpause = 0;
+ statsp->mac_stats.link_pause = 0;
+ statsp->mac_stats.lp_cap_autoneg = 0;
+ statsp->mac_stats.lp_cap_100T4 = 0;
+ statsp->mac_stats.lp_cap_1000fdx = 0;
+ statsp->mac_stats.lp_cap_1000hdx = 0;
+ statsp->mac_stats.lp_cap_100fdx = 0;
+ statsp->mac_stats.lp_cap_100hdx = 0;
+ statsp->mac_stats.lp_cap_10fdx = 0;
+ statsp->mac_stats.lp_cap_10hdx = 0;
+ statsp->mac_stats.lp_cap_10gfdx = 0;
+ statsp->mac_stats.lp_cap_10ghdx = 0;
+ statsp->mac_stats.lp_cap_asmpause = 0;
+ statsp->mac_stats.lp_cap_pause = 0;
+ }
+ } else
+ soft_bmsr->bits.auto_neg_complete = 1;
+
+ if ((bmsr_ints.bits.link_status ||
+ bmsr_ints.bits.auto_neg_complete) &&
+ soft_bmsr->bits.link_status &&
+ soft_bmsr->bits.auto_neg_complete) {
+ statsp->mac_stats.link_up = 1;
+ if (param_arr[param_autoneg].value) {
+ if ((status = nxge_mii_read(nxgep,
+ statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->anar),
+ &anar.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mii_read(nxgep,
+ statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->anlpar),
+ &anlpar.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mii_read(nxgep,
+ statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->aner),
+ &aner.value)) != NXGE_OK)
+ goto fail;
+ statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
+ statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
+ statsp->mac_stats.lp_cap_100fdx =
+ anlpar.bits.cap_100fdx;
+ statsp->mac_stats.lp_cap_100hdx =
+ anlpar.bits.cap_100hdx;
+ statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
+ statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
+ statsp->mac_stats.lp_cap_asmpause =
+ anlpar.bits.cap_asmpause;
+ statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
+ an_common.value = anar.value & anlpar.value;
+ if (param_arr[param_anar_1000fdx].value ||
+ param_arr[param_anar_1000hdx].value) {
+ if ((status = nxge_mii_read(nxgep,
+ statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->gsr),
+ &gsr.value))
+ != NXGE_OK)
+ goto fail;
+ statsp->mac_stats.lp_cap_1000fdx =
+ gsr.bits.link_1000fdx;
+ statsp->mac_stats.lp_cap_1000hdx =
+ gsr.bits.link_1000hdx;
+ if (param_arr[param_anar_1000fdx].value &&
+ gsr.bits.link_1000fdx) {
+ statsp->mac_stats.link_speed = 1000;
+ statsp->mac_stats.link_duplex = 2;
+ } else if (
+ param_arr[param_anar_1000hdx].value &&
+ gsr.bits.link_1000hdx) {
+ statsp->mac_stats.link_speed = 1000;
+ statsp->mac_stats.link_duplex = 1;
+ }
+ }
+ if ((an_common.value != 0) &&
+ !(statsp->mac_stats.link_speed)) {
+ if (an_common.bits.cap_100T4) {
+ statsp->mac_stats.link_T4 = 1;
+ statsp->mac_stats.link_speed = 100;
+ statsp->mac_stats.link_duplex = 1;
+ } else if (an_common.bits.cap_100fdx) {
+ statsp->mac_stats.link_speed = 100;
+ statsp->mac_stats.link_duplex = 2;
+ } else if (an_common.bits.cap_100hdx) {
+ statsp->mac_stats.link_speed = 100;
+ statsp->mac_stats.link_duplex = 1;
+ } else if (an_common.bits.cap_10fdx) {
+ statsp->mac_stats.link_speed = 10;
+ statsp->mac_stats.link_duplex = 2;
+ } else if (an_common.bits.cap_10hdx) {
+ statsp->mac_stats.link_speed = 10;
+ statsp->mac_stats.link_duplex = 1;
+ } else {
+ goto fail;
+ }
+ }
+ if (statsp->mac_stats.link_duplex != 1) {
+ statsp->mac_stats.link_asmpause =
+ an_common.bits.cap_asmpause;
+ if (statsp->mac_stats.link_asmpause)
+ if ((statsp->mac_stats.cap_pause == 0) &&
+ (statsp->mac_stats.lp_cap_pause
+ == 1))
+ statsp->mac_stats.link_pause
+ = 0;
+ else
+ statsp->mac_stats.link_pause
+ = 1;
+ else
+ statsp->mac_stats.link_pause =
+ an_common.bits.cap_pause;
+ }
+ }
+ nxge_link_is_up(nxgep);
+ }
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_mii_check: Unable to check MII"));
+ return (status);
+}
+
+/* Add a multicast address entry into the HW hash table */
+
+nxge_status_t
+nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
+{
+ uint32_t mchash;
+ p_hash_filter_t hash_filter;
+ uint16_t hash_bit;
+ boolean_t rx_init = B_FALSE;
+ uint_t j;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
+
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+ mchash = crc32_mchash(addrp);
+ if (nxgep->hash_filter == NULL) {
+ NXGE_DEBUG_MSG((NULL, STR_CTL,
+ "Allocating hash filter storage."));
+ nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
+ KM_SLEEP);
+ }
+ hash_filter = nxgep->hash_filter;
+ j = mchash / HASH_REG_WIDTH;
+ hash_bit = (1 << (mchash % HASH_REG_WIDTH));
+ hash_filter->hash_filter_regs[j] |= hash_bit;
+ hash_filter->hash_bit_ref_cnt[mchash]++;
+ if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
+ hash_filter->hash_ref_cnt++;
+ rx_init = B_TRUE;
+ }
+ if (rx_init) {
+ if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
+ goto fail;
+ }
+
+ RW_EXIT(&nxgep->filter_lock);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
+
+ return (NXGE_OK);
+fail:
+ RW_EXIT(&nxgep->filter_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
+ "Unable to add multicast address"));
+ return (status);
+}
+
+/* Remove a multicast address entry from the HW hash table */
+
+nxge_status_t
+nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
+{
+ uint32_t mchash;
+ p_hash_filter_t hash_filter;
+ uint16_t hash_bit;
+ boolean_t rx_init = B_FALSE;
+ uint_t j;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+ mchash = crc32_mchash(addrp);
+ if (nxgep->hash_filter == NULL) {
+ NXGE_DEBUG_MSG((NULL, STR_CTL,
+ "Hash filter already de_allocated."));
+ RW_EXIT(&nxgep->filter_lock);
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
+ return (NXGE_OK);
+ }
+ hash_filter = nxgep->hash_filter;
+ hash_filter->hash_bit_ref_cnt[mchash]--;
+ if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
+ j = mchash / HASH_REG_WIDTH;
+ hash_bit = (1 << (mchash % HASH_REG_WIDTH));
+ hash_filter->hash_filter_regs[j] &= ~hash_bit;
+ hash_filter->hash_ref_cnt--;
+ rx_init = B_TRUE;
+ }
+ if (hash_filter->hash_ref_cnt == 0) {
+ NXGE_DEBUG_MSG((NULL, STR_CTL,
+ "De-allocating hash filter storage."));
+ KMEM_FREE(hash_filter, sizeof (hash_filter_t));
+ nxgep->hash_filter = NULL;
+ }
+
+ if (rx_init) {
+ if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
+ goto fail;
+ }
+ RW_EXIT(&nxgep->filter_lock);
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
+
+ return (NXGE_OK);
+fail:
+ RW_EXIT(&nxgep->filter_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
+ "Unable to remove multicast address"));
+
+ return (status);
+}
+
+/* Set MAC address into MAC address HW registers */
+
+nxge_status_t
+nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
+
+ MUTEX_ENTER(&nxgep->ouraddr_lock);
+ /*
+ * Exit if the address is same as ouraddr or multicast or broadcast
+ */
+ if (((addrp->ether_addr_octet[0] & 01) == 1) ||
+ (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
+ (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
+ goto nxge_set_mac_addr_exit;
+ }
+ nxgep->ouraddr = *addrp;
+ /*
+ * Set new interface local address and re-init device.
+ * This is destructive to any other streams attached
+ * to this device.
+ */
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+ if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
+ goto fail;
+
+ RW_EXIT(&nxgep->filter_lock);
+ MUTEX_EXIT(&nxgep->ouraddr_lock);
+ goto nxge_set_mac_addr_end;
+nxge_set_mac_addr_exit:
+ MUTEX_EXIT(&nxgep->ouraddr_lock);
+nxge_set_mac_addr_end:
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
+
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&nxgep->ouraddr_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
+ "Unable to set mac address"));
+ return (status);
+}
+
+/* Check status of MII (MIF or PCS) link */
+
+nxge_status_t
+nxge_check_mii_link(p_nxge_t nxgep)
+{
+ mii_bmsr_t bmsr_ints, bmsr_data;
+ mii_anlpar_t anlpar;
+ mii_gsr_t gsr;
+ p_mii_regs_t mii_regs;
+ ddi_devstate_t dev_stat;
+ nxge_status_t status = NXGE_OK;
+ uint8_t portn;
+
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
+ portn));
+
+ mii_regs = NULL;
+
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+
+ dev_stat = FM_GET_DEVSTATE(nxgep);
+
+ if (dev_stat < DDI_DEVSTATE_DEGRADED) {
+ goto nxge_check_mii_link_exit;
+ }
+ if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
+ goto nxge_check_mii_link_exit;
+
+ if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->bmsr),
+ &bmsr_data.value)) != NXGE_OK)
+ goto fail;
+
+ if (nxgep->param_arr[param_autoneg].value) {
+ if ((status = nxge_mii_read(nxgep,
+ nxgep->statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->gsr),
+ &gsr.value)) != NXGE_OK)
+ goto fail;
+ if ((status = nxge_mii_read(nxgep,
+ nxgep->statsp->mac_stats.xcvr_portn,
+ (uint8_t)(uint64_t)(&mii_regs->anlpar),
+ &anlpar.value)) != NXGE_OK)
+ goto fail;
+ if (nxgep->statsp->mac_stats.link_up &&
+ ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
+ gsr.bits.link_1000fdx) ||
+ (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
+ gsr.bits.link_1000hdx) ||
+ (nxgep->statsp->mac_stats.lp_cap_100T4 ^
+ anlpar.bits.cap_100T4) ||
+ (nxgep->statsp->mac_stats.lp_cap_100fdx ^
+ anlpar.bits.cap_100fdx) ||
+ (nxgep->statsp->mac_stats.lp_cap_100hdx ^
+ anlpar.bits.cap_100hdx) ||
+ (nxgep->statsp->mac_stats.lp_cap_10fdx ^
+ anlpar.bits.cap_10fdx) ||
+ (nxgep->statsp->mac_stats.lp_cap_10hdx ^
+ anlpar.bits.cap_10hdx))) {
+ bmsr_data.bits.link_status = 0;
+ }
+ }
+
+ /* Workaround for link down issue */
+ if (bmsr_data.value == 0) {
+ cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
+ goto nxge_check_mii_link_exit;
+ }
+
+ bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
+ nxgep->bmsr.value = bmsr_data.value;
+ if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints)) != NXGE_OK)
+ goto fail;
+ if (FM_CHECK_DEV_HANDLE(nxgep) != DDI_SUCCESS) {
+ FM_REPORT_FAULT(nxgep, SERVICE_LOST, DEVICE_FAULT,
+ "register access fault detected in nxge_check_mii_link");
+ }
+
+nxge_check_mii_link_exit:
+ RW_EXIT(&nxgep->filter_lock);
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
+ portn));
+ return (NXGE_OK);
+
+fail:
+ RW_EXIT(&nxgep->filter_lock);
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_check_mii_link: Failed to check link port<%d>",
+ portn));
+ return (status);
+}
+
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_check_10g_link(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ ddi_devstate_t dev_stat;
+ nxge_status_t status = NXGE_OK;
+ boolean_t link_up;
+
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
+ portn));
+
+ dev_stat = FM_GET_DEVSTATE(nxgep);
+
+ if (dev_stat < DDI_DEVSTATE_DEGRADED) {
+ goto fail;
+ }
+
+ status = nxge_check_bcm8704_link(nxgep, &link_up);
+
+ if (status != NXGE_OK)
+ goto fail;
+
+ if (link_up) {
+ if (nxgep->statsp->mac_stats.link_up == 0) {
+ if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
+ goto fail;
+ nxgep->statsp->mac_stats.link_up = 1;
+ nxgep->statsp->mac_stats.link_speed = 10000;
+ nxgep->statsp->mac_stats.link_duplex = 2;
+
+ nxge_link_is_up(nxgep);
+ }
+ } else {
+ if (nxgep->statsp->mac_stats.link_up == 1) {
+ if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
+ goto fail;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Link down cable problem"));
+ nxgep->statsp->mac_stats.link_up = 0;
+ nxgep->statsp->mac_stats.link_speed = 0;
+ nxgep->statsp->mac_stats.link_duplex = 0;
+
+ nxge_link_is_down(nxgep);
+
+ }
+ }
+
+ if (FM_CHECK_DEV_HANDLE(nxgep) != DDI_SUCCESS) {
+ FM_REPORT_FAULT(nxgep, SERVICE_LOST, DEVICE_FAULT,
+ "register access fault detected in nxge_check_mii_link");
+ }
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
+ portn));
+ return (NXGE_OK);
+
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_check_10g_link: Failed to check link port<%d>",
+ portn));
+ return (status);
+}
+
+
+/* Declare link down */
+
+void
+nxge_link_is_down(p_nxge_t nxgep)
+{
+ p_nxge_stats_t statsp;
+ char link_stat_msg[64];
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
+
+ statsp = nxgep->statsp;
+ (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link down",
+ statsp->mac_stats.xcvr_portn);
+
+ if (nxge_no_msg == 0) {
+ FM_REPORT_FAULT(nxgep, SERVICE_DEGRADED, EXTERNAL_FAULT,
+ link_stat_msg);
+ }
+
+ mac_link_update(nxgep->mach, LINK_STATE_DOWN);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
+}
+
+/* Declare link up */
+
+void
+nxge_link_is_up(p_nxge_t nxgep)
+{
+ p_nxge_stats_t statsp;
+ char link_stat_msg[64];
+ uint32_t val;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
+
+ statsp = nxgep->statsp;
+ (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link up %d Mbps ",
+ statsp->mac_stats.xcvr_portn,
+ statsp->mac_stats.link_speed);
+
+ if (statsp->mac_stats.link_T4)
+ (void) strcat(link_stat_msg, "T4");
+ else if (statsp->mac_stats.link_duplex == 2)
+ (void) strcat(link_stat_msg, "full duplex");
+ else
+ (void) strcat(link_stat_msg, "half duplex");
+
+ (void) nxge_xif_init(nxgep);
+
+ if (nxge_no_msg == 0) {
+ FM_REPORT_FAULT(nxgep, SERVICE_RESTORED, EXTERNAL_FAULT,
+ link_stat_msg);
+ }
+
+ /* Clean up symbol errors incurred during link transition */
+ if (nxgep->mac.portmode == PORT_10G_FIBER) {
+ (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
+ XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
+ (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
+ XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
+ }
+
+ mac_link_update(nxgep->mach, LINK_STATE_UP);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
+}
+
+/*
+ * Calculate the bit in the multicast address filter
+ * that selects the given * address.
+ * Note: For GEM, the last 8-bits are used.
+ */
+uint32_t
+crc32_mchash(p_ether_addr_t addr)
+{
+ uint8_t *cp;
+ uint32_t crc;
+ uint32_t c;
+ int byte;
+ int bit;
+
+ cp = (uint8_t *)addr;
+ crc = (uint32_t)0xffffffff;
+ for (byte = 0; byte < 6; byte++) {
+ c = (uint32_t)cp[byte];
+ for (bit = 0; bit < 8; bit++) {
+ if ((c & 0x1) ^ (crc & 0x1))
+ crc = (crc >> 1)^0xedb88320;
+ else
+ crc = (crc >> 1);
+ c >>= 1;
+ }
+ }
+ return ((~crc) >> (32 - HASH_BITS));
+}
+
+/* Reset serdes */
+
+nxge_status_t
+nxge_serdes_reset(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+
+ handle = nxgep->npi_handle;
+
+ ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
+ drv_usecwait(500);
+ ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
+
+ return (NXGE_OK);
+}
+
+/* Monitor link status using interrupt or polling */
+
+nxge_status_t
+nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
+{
+ nxge_status_t status = NXGE_OK;
+
+ /*
+ * Make sure that we don't check the link if this happen to
+ * be not port0 or 1 and it is not BMAC port.
+ */
+ if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
+ return (NXGE_OK);
+
+ if (nxgep->statsp == NULL) {
+ /* stats has not been allocated. */
+ return (NXGE_OK);
+ }
+ /* Don't check link if we're not in internal loopback mode */
+ if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
+ return (NXGE_OK);
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_link_monitor port<%d> enable=%d",
+ nxgep->mac.portnum, enable));
+ if (enable == LINK_MONITOR_START) {
+ if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
+ if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
+ != NXGE_OK)
+ goto fail;
+ } else {
+ switch (nxgep->mac.portmode) {
+ case PORT_10G_FIBER:
+ nxgep->nxge_link_poll_timerid = timeout(
+ (fptrv_t)nxge_check_10g_link,
+ nxgep,
+ drv_usectohz(1000 * 1000));
+ break;
+
+ case PORT_1G_COPPER:
+ case PORT_1G_FIBER:
+ nxgep->nxge_link_poll_timerid = timeout(
+ (fptrv_t)nxge_check_mii_link,
+ nxgep,
+ drv_usectohz(1000 * 1000));
+ break;
+ default:
+ ;
+ }
+ }
+ } else {
+ if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
+ if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
+ != NXGE_OK)
+ goto fail;
+ } else {
+ if (nxgep->nxge_link_poll_timerid != 0) {
+ (void) untimeout(nxgep->nxge_link_poll_timerid);
+ nxgep->nxge_link_poll_timerid = 0;
+ }
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "<== nxge_link_monitor port<%d> enable=%d",
+ nxgep->mac.portnum, enable));
+ return (NXGE_OK);
+fail:
+ return (status);
+}
+
+/* Set promiscous mode */
+
+nxge_status_t
+nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_set_promisc: on %d", on));
+
+ nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
+
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+
+ if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
+ goto fail;
+ }
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
+ goto fail;
+ }
+
+ RW_EXIT(&nxgep->filter_lock);
+
+ if (on)
+ nxgep->statsp->mac_stats.promisc = B_TRUE;
+ else
+ nxgep->statsp->mac_stats.promisc = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
+
+ return (NXGE_OK);
+fail:
+ RW_EXIT(&nxgep->filter_lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
+ "Unable to set promisc (%d)", on));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+uint_t
+nxge_mif_intr(void *arg1, void *arg2)
+{
+#ifdef NXGE_DEBUG
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+#endif
+#if NXGE_MIF
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ uint32_t status;
+ npi_handle_t handle;
+ uint8_t portn;
+ p_nxge_stats_t statsp;
+#endif
+
+#ifdef NXGE_MIF
+ if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
+ nxgep = ldvp->nxgep;
+ }
+ nxgep = ldvp->nxgep;
+#endif
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
+ return (DDI_INTR_CLAIMED);
+
+mif_intr_fail:
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
+ return (DDI_INTR_UNCLAIMED);
+}
+
+/*ARGSUSED*/
+uint_t
+nxge_mac_intr(void *arg1, void *arg2)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ p_nxge_ldg_t ldgp;
+ uint32_t status;
+ npi_handle_t handle;
+ uint8_t portn;
+ p_nxge_stats_t statsp;
+ npi_status_t rs = NPI_SUCCESS;
+
+ if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
+ nxgep = ldvp->nxgep;
+ }
+
+ ldgp = ldvp->ldgp;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
+ "group %d", ldgp->ldg));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * This interrupt handler is for a specific
+ * mac port.
+ */
+ statsp = (p_nxge_stats_t)nxgep->statsp;
+ portn = nxgep->mac.portnum;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
+
+ if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
+ rs = npi_xmac_tx_get_istatus(handle, portn,
+ (xmac_tx_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+ if (status & ICFG_XMAC_TX_ALL) {
+ if (status & ICFG_XMAC_TX_UNDERRUN) {
+ statsp->xmac_stats.tx_underflow_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
+ }
+ if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
+ statsp->xmac_stats.tx_maxpktsize_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
+ }
+ if (status & ICFG_XMAC_TX_OVERFLOW) {
+ statsp->xmac_stats.tx_overflow_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_OVERFLOW);
+ }
+ if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
+ statsp->xmac_stats.tx_fifo_xfr_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
+ }
+ if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
+ statsp->xmac_stats.tx_byte_cnt +=
+ XTXMAC_BYTE_CNT_MASK;
+ }
+ if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
+ statsp->xmac_stats.tx_frame_cnt +=
+ XTXMAC_FRM_CNT_MASK;
+ }
+ }
+
+ rs = npi_xmac_rx_get_istatus(handle, portn,
+ (xmac_rx_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+ if (status & ICFG_XMAC_RX_ALL) {
+ if (status & ICFG_XMAC_RX_OVERFLOW)
+ statsp->xmac_stats.rx_overflow_err++;
+ if (status & ICFG_XMAC_RX_UNDERFLOW) {
+ statsp->xmac_stats.rx_underflow_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
+ }
+ if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
+ statsp->xmac_stats.rx_crc_err_cnt +=
+ XRXMAC_CRC_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
+ statsp->xmac_stats.rx_len_err_cnt +=
+ MAC_LEN_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
+ statsp->xmac_stats.rx_viol_err_cnt +=
+ XRXMAC_CD_VIO_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
+ statsp->xmac_stats.rx_byte_cnt +=
+ XRXMAC_BT_CNT_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
+ statsp->xmac_stats.rx_hist1_cnt +=
+ XRXMAC_HIST_CNT1_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
+ statsp->xmac_stats.rx_hist2_cnt +=
+ XRXMAC_HIST_CNT2_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
+ statsp->xmac_stats.rx_hist3_cnt +=
+ XRXMAC_HIST_CNT3_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
+ statsp->xmac_stats.rx_hist4_cnt +=
+ XRXMAC_HIST_CNT4_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
+ statsp->xmac_stats.rx_hist5_cnt +=
+ XRXMAC_HIST_CNT5_MASK;
+ }
+ if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
+ statsp->xmac_stats.rx_hist6_cnt +=
+ XRXMAC_HIST_CNT6_MASK;
+ }
+ if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
+ statsp->xmac_stats.rx_broadcast_cnt +=
+ XRXMAC_BC_FRM_CNT_MASK;
+ }
+ if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
+ statsp->xmac_stats.rx_mult_cnt +=
+ XRXMAC_MC_FRM_CNT_MASK;
+ }
+ if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
+ statsp->xmac_stats.rx_frag_cnt +=
+ XRXMAC_FRAG_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
+ statsp->xmac_stats.rx_frame_align_err_cnt +=
+ XRXMAC_AL_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
+ statsp->xmac_stats.rx_linkfault_err_cnt +=
+ XMAC_LINK_FLT_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
+ }
+ if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
+ statsp->xmac_stats.rx_remotefault_err++;
+ }
+ if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
+ statsp->xmac_stats.rx_localfault_err++;
+ }
+ }
+
+ rs = npi_xmac_ctl_get_istatus(handle, portn,
+ (xmac_ctl_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+ if (status & ICFG_XMAC_CTRL_ALL) {
+ if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
+ statsp->xmac_stats.rx_pause_cnt++;
+ if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
+ statsp->xmac_stats.tx_pause_state++;
+ if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
+ statsp->xmac_stats.tx_nopause_state++;
+ }
+ } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
+ rs = npi_bmac_tx_get_istatus(handle, portn,
+ (bmac_tx_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+ if (status & ICFG_BMAC_TX_ALL) {
+ if (status & ICFG_BMAC_TX_UNDERFLOW) {
+ statsp->bmac_stats.tx_underrun_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
+ }
+ if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
+ statsp->bmac_stats.tx_max_pkt_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
+ }
+ if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
+ statsp->bmac_stats.tx_byte_cnt +=
+ BTXMAC_BYTE_CNT_MASK;
+ }
+ if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
+ statsp->bmac_stats.tx_frame_cnt +=
+ BTXMAC_FRM_CNT_MASK;
+ }
+ }
+
+ rs = npi_bmac_rx_get_istatus(handle, portn,
+ (bmac_rx_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+ if (status & ICFG_BMAC_RX_ALL) {
+ if (status & ICFG_BMAC_RX_OVERFLOW) {
+ statsp->bmac_stats.rx_overflow_err++;
+ }
+ if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
+ statsp->bmac_stats.rx_frame_cnt +=
+ RXMAC_FRM_CNT_MASK;
+ }
+ if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
+ statsp->bmac_stats.rx_crc_err_cnt +=
+ BMAC_CRC_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
+ }
+ if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
+ statsp->bmac_stats.rx_len_err_cnt +=
+ MAC_LEN_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
+ }
+ if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
+ statsp->bmac_stats.rx_viol_err_cnt +=
+ BMAC_CD_VIO_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
+ }
+ if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
+ statsp->bmac_stats.rx_byte_cnt +=
+ BRXMAC_BYTE_CNT_MASK;
+ }
+ if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
+ statsp->bmac_stats.rx_align_err_cnt +=
+ BMAC_AL_ER_CNT_MASK;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
+ }
+
+ rs = npi_bmac_ctl_get_istatus(handle, portn,
+ (bmac_ctl_iconfig_t *)&status);
+ if (rs != NPI_SUCCESS)
+ goto npi_fail;
+
+ if (status & ICFG_BMAC_CTL_ALL) {
+ if (status & ICFG_BMAC_CTL_RCVPAUSE)
+ statsp->bmac_stats.rx_pause_cnt++;
+ if (status & ICFG_BMAC_CTL_INPAUSE_ST)
+ statsp->bmac_stats.tx_pause_state++;
+ if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
+ statsp->bmac_stats.tx_nopause_state++;
+ }
+ }
+
+ if (ldgp->nldvs == 1) {
+ (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ B_TRUE, ldgp->ldg_timer);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
+ return (DDI_INTR_CLAIMED);
+
+npi_fail:
+ NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
+ return (DDI_INTR_UNCLAIMED);
+}
+
+nxge_status_t
+nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
+{
+ uint8_t phy_port_addr;
+ nxge_status_t status = NXGE_OK;
+ boolean_t rx_sig_ok;
+ boolean_t pcs_blk_lock;
+ boolean_t link_align;
+ uint16_t val1, val2, val3;
+#ifdef NXGE_DEBUG_SYMBOL_ERR
+ uint16_t val_debug;
+ uint16_t val;
+#endif
+
+ phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
+
+#ifdef NXGE_DEBUG_SYMBOL_ERR
+ /* Check Device 3 Register Device 3 0xC809 */
+ (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
+ if ((val_debug & ~0x200) != 0) {
+ cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
+ nxgep->mac.portnum, val_debug);
+ (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
+ &val_debug);
+ cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
+ nxgep->mac.portnum, val_debug);
+ }
+
+ (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
+ XPCS_REG_DESCWERR_COUNTER, &val);
+ if (val != 0)
+ cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
+
+ (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
+ XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
+ if (val != 0)
+ cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
+
+ (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
+ XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
+ if (val != 0)
+ cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
+#endif
+
+ /* Check from BCM8704 if 10G link is up or down */
+
+ /* Check Device 1 Register 0xA bit0 */
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_PMA_PMD_DEV_ADDR,
+ BCM8704_PMD_RECEIVE_SIG_DETECT,
+ &val1);
+ if (status != NXGE_OK)
+ goto fail;
+ rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
+
+ /* Check Device 3 Register 0x20 bit0 */
+ if ((status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_PCS_DEV_ADDR,
+ BCM8704_10GBASE_R_PCS_STATUS_REG,
+ &val2)) != NPI_SUCCESS)
+ goto fail;
+ pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
+
+ /* Check Device 4 Register 0x18 bit12 */
+ status = nxge_mdio_read(nxgep, phy_port_addr,
+ BCM8704_PHYXS_ADDR,
+ BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
+ &val3);
+ if (status != NXGE_OK)
+ goto fail;
+ link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
+ XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
+ XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
+
+#ifdef NXGE_DEBUG_ALIGN_ERR
+ /* Temp workaround for link down issue */
+ if (pcs_blk_lock == B_FALSE) {
+ if (val2 != 0x4) {
+ pcs_blk_lock = B_TRUE;
+ cmn_err(CE_NOTE,
+ "!LINK DEBUG: port%d PHY Dev3 "
+ "Reg 0x20 = 0x%x\n",
+ nxgep->mac.portnum, val2);
+ }
+ }
+
+ if (link_align == B_FALSE) {
+ if (val3 != 0x140f) {
+ link_align = B_TRUE;
+ cmn_err(CE_NOTE,
+ "!LINK DEBUG: port%d PHY Dev4 "
+ "Reg 0x18 = 0x%x\n",
+ nxgep->mac.portnum, val3);
+ }
+ }
+
+ if (rx_sig_ok == B_FALSE) {
+ if ((val2 == 0) || (val3 == 0)) {
+ rx_sig_ok = B_TRUE;
+ cmn_err(CE_NOTE,
+ "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
+ nxgep->mac.portnum);
+ }
+ }
+#endif
+
+ *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
+ (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
+
+ return (NXGE_OK);
+fail:
+ return (status);
+}
+
+
+nxge_status_t
+nxge_get_xcvr_type(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+#if defined(_BIG_ENDIAN)
+ char *prop_val;
+
+ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
+ if (strcmp("xgf", prop_val) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
+ nxgep->mac.portmode = PORT_10G_FIBER;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr"));
+ } else if (strcmp("mif", prop_val) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ nxgep->mac.portmode = PORT_1G_COPPER;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
+ } else if (strcmp("pcs", prop_val) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ nxgep->mac.portmode = PORT_1G_FIBER;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr"));
+ } else if (strcmp("xgc", prop_val) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
+ nxgep->mac.portmode = PORT_10G_COPPER;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Unknown phy-type: %s",
+ prop_val));
+ ddi_prop_free(prop_val);
+ return (NXGE_ERROR);
+ }
+ status = NXGE_OK;
+ (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
+ "phy-type", prop_val);
+ ddi_prop_free(prop_val);
+ } else {
+ /*
+ * This should really be an error. But for now default
+ * this to 10G fiber.
+ */
+ if (nxgep->niu_type == N2_NIU) {
+ nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
+ nxgep->mac.portmode = PORT_10G_FIBER;
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Cannot find phy-type: "
+ " Default to 10G Fiber Xcvr"));
+ status = NXGE_OK;
+ } else {
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "Cannot get phy-type"));
+ return (NXGE_ERROR);
+ }
+ }
+#else
+ status = nxge_espc_phy_type_get(nxgep);
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
+ return (status);
+}
+
+nxge_status_t
+nxge_10g_link_led_on(p_nxge_t nxgep)
+{
+ if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
+ != NPI_SUCCESS)
+ return (NXGE_ERROR);
+ else
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_10g_link_led_off(p_nxge_t nxgep)
+{
+ if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
+ != NPI_SUCCESS)
+ return (NXGE_ERROR);
+ else
+ return (NXGE_OK);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_main.c b/usr/src/uts/sun4v/io/nxge/nxge_main.c
new file mode 100644
index 0000000000..cf4e79804c
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_main.c
@@ -0,0 +1,4226 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
+ */
+#include <sys/nxge/nxge_impl.h>
+
+uint32_t nxge_use_partition = 0; /* debug partition flag */
+uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */
+uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */
+/*
+ * until MSIX supported, assume msi, use 2 for msix
+ */
+uint32_t nxge_msi_enable = 1; /* debug: turn msi off */
+
+/*
+ * Globals: tunable parameters (/etc/system or adb)
+ *
+ */
+uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
+uint32_t nxge_rbr_spare_size = 0;
+uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT;
+uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
+uint32_t nxge_no_msg = 0; /* control message display */
+uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */
+uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX;
+uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN;
+uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN;
+uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU;
+boolean_t nxge_jumbo_enable = B_FALSE;
+uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT;
+uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD;
+
+/*
+ * Debugging flags:
+ * nxge_no_tx_lb : transmit load balancing
+ * nxge_tx_lb_policy: 0 - TCP port (default)
+ * 3 - DEST MAC
+ */
+uint32_t nxge_no_tx_lb = 0;
+uint32_t nxge_tx_lb_policy = NXGE_TX_LB_TCPUDP;
+
+/*
+ * Add tunable to reduce the amount of time spent in the
+ * ISR doing Rx Processing.
+ */
+uint32_t nxge_max_rx_pkts = 1024;
+
+/*
+ * Tunables to manage the receive buffer blocks.
+ *
+ * nxge_rx_threshold_hi: copy all buffers.
+ * nxge_rx_bcopy_size_type: receive buffer block size type.
+ * nxge_rx_threshold_lo: copy only up to tunable block size type.
+ */
+nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
+nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
+nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
+
+rtrace_t npi_rtracebuf;
+
+#if defined(sun4v)
+/*
+ * Hypervisor N2/NIU services information.
+ */
+static hsvc_info_t niu_hsvc = {
+ HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
+ NIU_MINOR_VER, "nxge"
+};
+#endif
+
+/*
+ * Function Prototypes
+ */
+static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
+static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
+static void nxge_unattach(p_nxge_t);
+
+#if NXGE_PROPERTY
+static void nxge_remove_hard_properties(p_nxge_t);
+#endif
+
+static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
+
+static nxge_status_t nxge_setup_mutexes(p_nxge_t);
+static void nxge_destroy_mutexes(p_nxge_t);
+
+static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
+static void nxge_unmap_regs(p_nxge_t nxgep);
+#ifdef NXGE_DEBUG
+static void nxge_test_map_regs(p_nxge_t nxgep);
+#endif
+
+static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
+static nxge_status_t nxge_add_soft_intrs(p_nxge_t nxgep);
+static void nxge_remove_intrs(p_nxge_t nxgep);
+static void nxge_remove_soft_intrs(p_nxge_t nxgep);
+
+static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
+static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
+static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
+static void nxge_intrs_enable(p_nxge_t nxgep);
+static void nxge_intrs_disable(p_nxge_t nxgep);
+
+static void nxge_suspend(p_nxge_t);
+static nxge_status_t nxge_resume(p_nxge_t);
+
+static nxge_status_t nxge_setup_dev(p_nxge_t);
+static void nxge_destroy_dev(p_nxge_t);
+
+static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
+static void nxge_free_mem_pool(p_nxge_t);
+
+static nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
+static void nxge_free_rx_mem_pool(p_nxge_t);
+
+static nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
+static void nxge_free_tx_mem_pool(p_nxge_t);
+
+static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
+ struct ddi_dma_attr *,
+ size_t, ddi_device_acc_attr_t *, uint_t,
+ p_nxge_dma_common_t);
+
+static void nxge_dma_mem_free(p_nxge_dma_common_t);
+
+static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
+static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
+
+static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, size_t);
+static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
+
+static nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
+static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
+
+static nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *,
+ size_t);
+static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
+
+static int nxge_init_common_dev(p_nxge_t);
+static void nxge_uninit_common_dev(p_nxge_t);
+
+/*
+ * The next declarations are for the GLDv3 interface.
+ */
+static int nxge_m_start(void *);
+static void nxge_m_stop(void *);
+static int nxge_m_unicst(void *, const uint8_t *);
+static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
+static int nxge_m_promisc(void *, boolean_t);
+static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
+static void nxge_m_resources(void *);
+mblk_t *nxge_m_tx(void *arg, mblk_t *);
+static nxge_status_t nxge_mac_register(p_nxge_t);
+
+#define NXGE_NEPTUNE_MAGIC 0x4E584745UL
+#define MAX_DUMP_SZ 256
+
+#define NXGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+
+static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *);
+static mac_callbacks_t nxge_m_callbacks = {
+ NXGE_M_CALLBACK_FLAGS,
+ nxge_m_stat,
+ nxge_m_start,
+ nxge_m_stop,
+ nxge_m_promisc,
+ nxge_m_multicst,
+ nxge_m_unicst,
+ nxge_m_tx,
+ nxge_m_resources,
+ nxge_m_ioctl,
+ nxge_m_getcapab
+};
+
+void
+nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
+
+/*
+ * These global variables control the message
+ * output.
+ */
+out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
+uint64_t nxge_debug_level = 0;
+
+/*
+ * This list contains the instance structures for the Neptune
+ * devices present in the system. The lock exists to guarantee
+ * mutually exclusive access to the list.
+ */
+void *nxge_list = NULL;
+
+void *nxge_hw_list = NULL;
+nxge_os_mutex_t nxge_common_lock;
+
+nxge_os_mutex_t nxge_mii_lock;
+static uint32_t nxge_mii_lock_init = 0;
+nxge_os_mutex_t nxge_mdio_lock;
+static uint32_t nxge_mdio_lock_init = 0;
+
+extern uint64_t npi_debug_level;
+
+extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *);
+extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *);
+extern nxge_status_t nxge_ldgv_uninit(p_nxge_t);
+extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t);
+extern void nxge_fm_init(p_nxge_t,
+ ddi_device_acc_attr_t *,
+ ddi_device_acc_attr_t *,
+ ddi_dma_attr_t *);
+extern void nxge_fm_fini(p_nxge_t);
+
+/*
+ * Count used to maintain the number of buffers being used
+ * by Neptune instances and loaned up to the upper layers.
+ */
+uint32_t nxge_mblks_pending = 0;
+
+/*
+ * Device register access attributes for PIO.
+ */
+static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC,
+};
+
+/*
+ * Device descriptor access attributes for DMA.
+ */
+static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_LE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+/*
+ * Device buffer access attributes for DMA.
+ */
+static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_STRUCTURE_BE_ACC,
+ DDI_STRICTORDER_ACC
+};
+
+ddi_dma_attr_t nxge_desc_dma_attr = {
+ DMA_ATTR_V0, /* version number. */
+ 0, /* low address */
+ 0xffffffffffffffff, /* high address */
+ 0xffffffffffffffff, /* address counter max */
+#ifndef NIU_PA_WORKAROUND
+ 0x100000, /* alignment */
+#else
+ 0x2000,
+#endif
+ 0xfc00fc, /* dlim_burstsizes */
+ 0x1, /* minimum transfer size */
+ 0xffffffffffffffff, /* maximum transfer size */
+ 0xffffffffffffffff, /* maximum segment size */
+ 1, /* scatter/gather list length */
+ (unsigned int) 1, /* granularity */
+ 0 /* attribute flags */
+};
+
+ddi_dma_attr_t nxge_tx_dma_attr = {
+ DMA_ATTR_V0, /* version number. */
+ 0, /* low address */
+ 0xffffffffffffffff, /* high address */
+ 0xffffffffffffffff, /* address counter max */
+#if defined(_BIG_ENDIAN)
+ 0x2000, /* alignment */
+#else
+ 0x1000, /* alignment */
+#endif
+ 0xfc00fc, /* dlim_burstsizes */
+ 0x1, /* minimum transfer size */
+ 0xffffffffffffffff, /* maximum transfer size */
+ 0xffffffffffffffff, /* maximum segment size */
+ 5, /* scatter/gather list length */
+ (unsigned int) 1, /* granularity */
+ 0 /* attribute flags */
+};
+
+ddi_dma_attr_t nxge_rx_dma_attr = {
+ DMA_ATTR_V0, /* version number. */
+ 0, /* low address */
+ 0xffffffffffffffff, /* high address */
+ 0xffffffffffffffff, /* address counter max */
+ 0x2000, /* alignment */
+ 0xfc00fc, /* dlim_burstsizes */
+ 0x1, /* minimum transfer size */
+ 0xffffffffffffffff, /* maximum transfer size */
+ 0xffffffffffffffff, /* maximum segment size */
+ 1, /* scatter/gather list length */
+ (unsigned int) 1, /* granularity */
+ 0 /* attribute flags */
+};
+
+ddi_dma_lim_t nxge_dma_limits = {
+ (uint_t)0, /* dlim_addr_lo */
+ (uint_t)0xffffffff, /* dlim_addr_hi */
+ (uint_t)0xffffffff, /* dlim_cntr_max */
+ (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */
+ 0x1, /* dlim_minxfer */
+ 1024 /* dlim_speed */
+};
+
+dma_method_t nxge_force_dma = DVMA;
+
+/*
+ * dma chunk sizes.
+ *
+ * Try to allocate the largest possible size
+ * so that fewer number of dma chunks would be managed
+ */
+#ifdef NIU_PA_WORKAROUND
+size_t alloc_sizes [] = {0x2000};
+#else
+size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
+ 0x10000, 0x20000, 0x40000, 0x80000,
+ 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000};
+#endif
+
+/*
+ * Translate "dev_t" to a pointer to the associated "dev_info_t".
+ */
+
+static int
+nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ p_nxge_t nxgep = NULL;
+ int instance;
+ int status = DDI_SUCCESS;
+ nxge_status_t nxge_status = NXGE_OK;
+ uint8_t portn;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
+
+ /*
+ * Get the device instance since we'll need to setup
+ * or retrieve a soft state for this instance.
+ */
+ instance = ddi_get_instance(dip);
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
+ break;
+
+ case DDI_RESUME:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
+ nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
+ if (nxgep == NULL) {
+ status = DDI_FAILURE;
+ break;
+ }
+ if (nxgep->dip != dip) {
+ status = DDI_FAILURE;
+ break;
+ }
+ if (nxgep->suspended == DDI_PM_SUSPEND) {
+ status = ddi_dev_is_needed(nxgep->dip, 0, 1);
+ } else {
+ nxge_status = nxge_resume(nxgep);
+ }
+ goto nxge_attach_exit;
+
+ case DDI_PM_RESUME:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
+ nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
+ if (nxgep == NULL) {
+ status = DDI_FAILURE;
+ break;
+ }
+ if (nxgep->dip != dip) {
+ status = DDI_FAILURE;
+ break;
+ }
+ nxge_status = nxge_resume(nxgep);
+ goto nxge_attach_exit;
+
+ default:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
+ status = DDI_FAILURE;
+ goto nxge_attach_exit;
+ }
+
+
+ if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
+ status = DDI_FAILURE;
+ goto nxge_attach_exit;
+ }
+
+ nxgep = ddi_get_soft_state(nxge_list, instance);
+ if (nxgep == NULL) {
+ goto nxge_attach_fail;
+ }
+
+ nxgep->drv_state = 0;
+ nxgep->dip = dip;
+ nxgep->instance = instance;
+ nxgep->p_dip = ddi_get_parent(dip);
+ nxgep->nxge_debug_level = nxge_debug_level;
+ npi_debug_level = nxge_debug_level;
+
+ nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_dev_desc_dma_acc_attr,
+ &nxge_rx_dma_attr);
+
+ status = nxge_map_regs(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
+ goto nxge_attach_fail;
+ }
+
+ status = nxge_init_common_dev(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_init_common_dev failed"));
+ goto nxge_attach_fail;
+ }
+
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+ nxgep->mac.portnum = portn;
+ if ((portn == 0) || (portn == 1))
+ nxgep->mac.porttype = PORT_TYPE_XMAC;
+ else
+ nxgep->mac.porttype = PORT_TYPE_BMAC;
+
+ /*
+ * Setup the Ndd parameters for the this instance.
+ */
+ nxge_init_param(nxgep);
+
+ /*
+ * Setup Register Tracing Buffer.
+ */
+ npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
+
+ /* init stats ptr */
+ nxge_init_statsp(nxgep);
+ status = nxge_get_xcvr_type(nxgep);
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
+ " Couldn't determine card type"
+ " .... exit "));
+ goto nxge_attach_fail;
+ }
+
+ if ((nxgep->niu_type == NEPTUNE) &&
+ (nxgep->mac.portmode == PORT_10G_FIBER)) {
+ nxgep->niu_type = NEPTUNE_2;
+ }
+
+ status = nxge_get_config_properties(nxgep);
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "get_hw create failed"));
+ goto nxge_attach_fail;
+ }
+
+ nxge_get_xcvr_properties(nxgep);
+
+ /*
+ * Setup the Kstats for the driver.
+ */
+ nxge_setup_kstats(nxgep);
+
+ nxge_setup_param(nxgep);
+
+ status = nxge_setup_system_dma_pages(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
+ goto nxge_attach_fail;
+ }
+
+#if defined(sun4v)
+ if (nxgep->niu_type == N2_NIU) {
+ nxgep->niu_hsvc_available = B_FALSE;
+ bcopy(&niu_hsvc, &nxgep->niu_hsvc, sizeof (hsvc_info_t));
+ if ((status =
+ hsvc_register(&nxgep->niu_hsvc,
+ &nxgep->niu_min_ver)) != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_attach: "
+ "%s: cannot negotiate "
+ "hypervisor services "
+ "revision %d "
+ "group: 0x%lx "
+ "major: 0x%lx minor: 0x%lx "
+ "errno: %d",
+ niu_hsvc.hsvc_modname,
+ niu_hsvc.hsvc_rev,
+ niu_hsvc.hsvc_group,
+ niu_hsvc.hsvc_major,
+ niu_hsvc.hsvc_minor,
+ status));
+ status = DDI_FAILURE;
+ goto nxge_attach_fail;
+ }
+
+ nxgep->niu_hsvc_available = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "NIU Hypervisor service enabled"));
+ }
+#endif
+
+ nxge_hw_id_init(nxgep);
+ nxge_hw_init_niu_common(nxgep);
+
+ status = nxge_setup_mutexes(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
+ goto nxge_attach_fail;
+ }
+
+ status = nxge_setup_dev(nxgep);
+ if (status != DDI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
+ goto nxge_attach_fail;
+ }
+
+ status = nxge_add_intrs(nxgep);
+ if (status != DDI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
+ goto nxge_attach_fail;
+ }
+ status = nxge_add_soft_intrs(nxgep);
+ if (status != DDI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "add_soft_intr failed"));
+ goto nxge_attach_fail;
+ }
+
+ /*
+ * Enable interrupts.
+ */
+ nxge_intrs_enable(nxgep);
+
+ if ((status = nxge_mac_register(nxgep)) != DDI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "unable to register to mac layer (%d)", status));
+ goto nxge_attach_fail;
+ }
+
+ mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "registered to mac (instance %d)",
+ instance));
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+
+ goto nxge_attach_exit;
+
+nxge_attach_fail:
+ nxge_unattach(nxgep);
+ if (nxge_status != NXGE_OK)
+ nxge_status = (NXGE_ERROR | NXGE_DDI_FAILED);
+ nxgep = NULL;
+
+nxge_attach_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
+ status));
+
+ return (status);
+}
+
+static int
+nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ int status = DDI_SUCCESS;
+ int instance;
+ p_nxge_t nxgep = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
+ instance = ddi_get_instance(dip);
+ nxgep = ddi_get_soft_state(nxge_list, instance);
+ if (nxgep == NULL) {
+ status = DDI_FAILURE;
+ goto nxge_detach_exit;
+ }
+
+ switch (cmd) {
+ case DDI_DETACH:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
+ break;
+
+ case DDI_PM_SUSPEND:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
+ nxgep->suspended = DDI_PM_SUSPEND;
+ nxge_suspend(nxgep);
+ break;
+
+ case DDI_SUSPEND:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
+ if (nxgep->suspended != DDI_PM_SUSPEND) {
+ nxgep->suspended = DDI_SUSPEND;
+ nxge_suspend(nxgep);
+ }
+ break;
+
+ default:
+ status = DDI_FAILURE;
+ }
+
+ if (cmd != DDI_DETACH)
+ goto nxge_detach_exit;
+
+ /*
+ * Stop the xcvr polling.
+ */
+ nxgep->suspended = cmd;
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+
+ if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_detach status = 0x%08X", status));
+ return (DDI_FAILURE);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_detach (mac_unregister) status = 0x%08X", status));
+
+ nxge_unattach(nxgep);
+ nxgep = NULL;
+
+nxge_detach_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X",
+ status));
+
+ return (status);
+}
+
+static void
+nxge_unattach(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach"));
+
+ if (nxgep == NULL || nxgep->dev_regs == NULL) {
+ return;
+ }
+
+ if (nxgep->nxge_hw_p) {
+ nxge_uninit_common_dev(nxgep);
+ nxgep->nxge_hw_p = NULL;
+ }
+
+ if (nxgep->nxge_timerid) {
+ nxge_stop_timer(nxgep, nxgep->nxge_timerid);
+ nxgep->nxge_timerid = 0;
+ }
+
+#if defined(sun4v)
+ if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) {
+ (void) hsvc_unregister(&nxgep->niu_hsvc);
+ nxgep->niu_hsvc_available = B_FALSE;
+ }
+#endif
+ /*
+ * Stop any further interrupts.
+ */
+ nxge_remove_intrs(nxgep);
+
+ /* remove soft interrups */
+ nxge_remove_soft_intrs(nxgep);
+
+ /*
+ * Stop the device and free resources.
+ */
+ nxge_destroy_dev(nxgep);
+
+ /*
+ * Tear down the ndd parameters setup.
+ */
+ nxge_destroy_param(nxgep);
+
+ /*
+ * Tear down the kstat setup.
+ */
+ nxge_destroy_kstats(nxgep);
+
+ /*
+ * Destroy all mutexes.
+ */
+ nxge_destroy_mutexes(nxgep);
+
+ /*
+ * Remove the list of ndd parameters which
+ * were setup during attach.
+ */
+ if (nxgep->dip) {
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ " nxge_unattach: remove all properties"));
+
+ (void) ddi_prop_remove_all(nxgep->dip);
+ }
+
+#if NXGE_PROPERTY
+ nxge_remove_hard_properties(nxgep);
+#endif
+
+ /*
+ * Unmap the register setup.
+ */
+ nxge_unmap_regs(nxgep);
+
+ nxge_fm_fini(nxgep);
+
+ ddi_soft_state_free(nxge_list, nxgep->instance);
+
+ NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach"));
+}
+
+static char n2_siu_name[] = "niu";
+
+static nxge_status_t
+nxge_map_regs(p_nxge_t nxgep)
+{
+ int ddi_status = DDI_SUCCESS;
+ p_dev_regs_t dev_regs;
+ char buf[MAXPATHLEN + 1];
+ char *devname;
+#ifdef NXGE_DEBUG
+ char *sysname;
+#endif
+ off_t regsize;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs"));
+ nxgep->dev_regs = NULL;
+ dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
+ dev_regs->nxge_regh = NULL;
+ dev_regs->nxge_pciregh = NULL;
+ dev_regs->nxge_msix_regh = NULL;
+ dev_regs->nxge_vir_regh = NULL;
+ dev_regs->nxge_vir2_regh = NULL;
+ nxgep->niu_type = NEPTUNE;
+
+ devname = ddi_pathname(nxgep->dip, buf);
+ ASSERT(strlen(devname) > 0);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: pathname devname %s", devname));
+
+ if (strstr(devname, n2_siu_name)) {
+ /* N2/NIU */
+ nxgep->niu_type = N2_NIU;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: N2/NIU devname %s", devname));
+ /* get function number */
+ nxgep->function_num =
+ (devname[strlen(devname) -1] == '1' ? 1 : 0);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: N2/NIU function number %d",
+ nxgep->function_num));
+ } else {
+ int *prop_val;
+ uint_t prop_len;
+ uint8_t func_num;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
+ 0, "reg",
+ &prop_val, &prop_len) != DDI_PROP_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL,
+ "Reg property not found"));
+ ddi_status = DDI_FAILURE;
+ goto nxge_map_regs_fail0;
+
+ } else {
+ func_num = (prop_val[0] >> 8) & 0x7;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "Reg property found: fun # %d",
+ func_num));
+ nxgep->function_num = func_num;
+ ddi_prop_free(prop_val);
+ }
+ }
+
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ default:
+ (void) ddi_dev_regsize(nxgep->dip, 0, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: pci config size 0x%x", regsize));
+
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 0,
+ (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs, nxge bus config regs failed"));
+ goto nxge_map_regs_fail0;
+ }
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_reg: PCI config addr 0x%0llx "
+ " handle 0x%0llx", dev_regs->nxge_pciregp,
+ dev_regs->nxge_pciregh));
+ /*
+ * IMP IMP
+ * workaround for bit swapping bug in HW
+ * which ends up in no-snoop = yes
+ * resulting, in DMA not synched properly
+ */
+#if !defined(_BIG_ENDIAN)
+ /* workarounds */
+ pci_config_put16(dev_regs->nxge_pciregh, 0x88, 0x80f);
+#endif
+ (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: pio size 0x%x", regsize));
+ /* set up the device mapped register */
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
+ (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for Neptune global reg failed"));
+ goto nxge_map_regs_fail1;
+ }
+
+ /* set up the msi/msi-x mapped register */
+ (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: msix size 0x%x", regsize));
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
+ (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for msi reg failed"));
+ goto nxge_map_regs_fail2;
+ }
+
+ /* set up the vio region mapped register */
+ (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: vio size 0x%x", regsize));
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
+ (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
+
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for nxge vio reg failed"));
+ goto nxge_map_regs_fail3;
+ }
+ nxgep->dev_regs = dev_regs;
+
+ NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh);
+ NPI_PCI_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_pciregp);
+ NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh);
+ NPI_MSI_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_msix_regp);
+
+ NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
+ NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
+
+ NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
+ NPI_REG_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_regp);
+
+ NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
+ NPI_VREG_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
+
+ break;
+
+ case N2_NIU:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU"));
+ /*
+ * Set up the device mapped register (FWARC 2006/556)
+ * (changed back to 1: reg starts at 1!)
+ */
+ (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: dev size 0x%x", regsize));
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
+ (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
+
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for N2/NIU, global reg failed "));
+ goto nxge_map_regs_fail1;
+ }
+
+ /* set up the vio region mapped register */
+ (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: vio (1) size 0x%x", regsize));
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
+ (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
+
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for nxge vio reg failed"));
+ goto nxge_map_regs_fail2;
+ }
+ /* set up the vio region mapped register */
+ (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_map_regs: vio (3) size 0x%x", regsize));
+ ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
+ (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0,
+ &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh);
+
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_map_regs for nxge vio2 reg failed"));
+ goto nxge_map_regs_fail3;
+ }
+ nxgep->dev_regs = dev_regs;
+
+ NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
+ NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
+
+ NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
+ NPI_REG_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_regp);
+
+ NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
+ NPI_VREG_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
+
+ NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh);
+ NPI_V2REG_ADD_HANDLE_SET(nxgep,
+ (npi_reg_ptr_t)dev_regs->nxge_vir2_regp);
+
+ break;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx "
+ " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh));
+
+ goto nxge_map_regs_exit;
+nxge_map_regs_fail3:
+ if (dev_regs->nxge_msix_regh) {
+ ddi_regs_map_free(&dev_regs->nxge_msix_regh);
+ }
+ if (dev_regs->nxge_vir_regh) {
+ ddi_regs_map_free(&dev_regs->nxge_regh);
+ }
+nxge_map_regs_fail2:
+ if (dev_regs->nxge_regh) {
+ ddi_regs_map_free(&dev_regs->nxge_regh);
+ }
+nxge_map_regs_fail1:
+ if (dev_regs->nxge_pciregh) {
+ ddi_regs_map_free(&dev_regs->nxge_pciregh);
+ }
+nxge_map_regs_fail0:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory"));
+ kmem_free(dev_regs, sizeof (dev_regs_t));
+
+nxge_map_regs_exit:
+ if (ddi_status != DDI_SUCCESS)
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs"));
+ return (status);
+}
+
+static void
+nxge_unmap_regs(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs"));
+ if (nxgep->dev_regs) {
+ if (nxgep->dev_regs->nxge_pciregh) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_unmap_regs: bus"));
+ ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh);
+ nxgep->dev_regs->nxge_pciregh = NULL;
+ }
+ if (nxgep->dev_regs->nxge_regh) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_unmap_regs: device registers"));
+ ddi_regs_map_free(&nxgep->dev_regs->nxge_regh);
+ nxgep->dev_regs->nxge_regh = NULL;
+ }
+ if (nxgep->dev_regs->nxge_msix_regh) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_unmap_regs: device interrupts"));
+ ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh);
+ nxgep->dev_regs->nxge_msix_regh = NULL;
+ }
+ if (nxgep->dev_regs->nxge_vir_regh) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_unmap_regs: vio region"));
+ ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh);
+ nxgep->dev_regs->nxge_vir_regh = NULL;
+ }
+ if (nxgep->dev_regs->nxge_vir2_regh) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_unmap_regs: vio2 region"));
+ ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh);
+ nxgep->dev_regs->nxge_vir2_regh = NULL;
+ }
+
+ kmem_free(nxgep->dev_regs, sizeof (dev_regs_t));
+ nxgep->dev_regs = NULL;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs"));
+}
+
+static nxge_status_t
+nxge_setup_mutexes(p_nxge_t nxgep)
+{
+ int ddi_status = DDI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ nxge_classify_t *classify_ptr;
+ int partition;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes"));
+
+ /*
+ * Get the interrupt cookie so the mutexes can be
+ * Initialised.
+ */
+ ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0,
+ &nxgep->interrupt_cookie);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_setup_mutexes: failed 0x%x", ddi_status));
+ goto nxge_setup_mutexes_exit;
+ }
+
+ /* Initialize global mutex */
+
+ if (nxge_mdio_lock_init == 0) {
+ MUTEX_INIT(&nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL);
+ }
+ atomic_add_32(&nxge_mdio_lock_init, 1);
+
+ if (nxge_mii_lock_init == 0) {
+ MUTEX_INIT(&nxge_mii_lock, NULL, MUTEX_DRIVER, NULL);
+ }
+ atomic_add_32(&nxge_mii_lock_init, 1);
+
+ nxgep->drv_state |= STATE_MDIO_LOCK_INIT;
+ nxgep->drv_state |= STATE_MII_LOCK_INIT;
+
+ /*
+ * Initialize mutex's for this device.
+ */
+ MUTEX_INIT(nxgep->genlock, NULL,
+ MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ MUTEX_INIT(&nxgep->ouraddr_lock, NULL,
+ MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ MUTEX_INIT(&nxgep->mif_lock, NULL,
+ MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ RW_INIT(&nxgep->filter_lock, NULL,
+ RW_DRIVER, (void *)nxgep->interrupt_cookie);
+
+ classify_ptr = &nxgep->classifier;
+ /*
+ * FFLP Mutexes are never used in interrupt context
+ * as fflp operation can take very long time to
+ * complete and hence not suitable to invoke from interrupt
+ * handlers.
+ */
+ MUTEX_INIT(&classify_ptr->tcam_lock, NULL,
+ NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ if (nxgep->niu_type == NEPTUNE) {
+ MUTEX_INIT(&classify_ptr->fcram_lock, NULL,
+ NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ for (partition = 0; partition < MAX_PARTITION; partition++) {
+ MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL,
+ NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
+ }
+ }
+
+nxge_setup_mutexes_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_setup_mutexes status = %x", status));
+
+ if (ddi_status != DDI_SUCCESS)
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+
+ return (status);
+}
+
+static void
+nxge_destroy_mutexes(p_nxge_t nxgep)
+{
+ int partition;
+ nxge_classify_t *classify_ptr;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes"));
+ RW_DESTROY(&nxgep->filter_lock);
+ MUTEX_DESTROY(&nxgep->mif_lock);
+ MUTEX_DESTROY(&nxgep->ouraddr_lock);
+ MUTEX_DESTROY(nxgep->genlock);
+
+ classify_ptr = &nxgep->classifier;
+ MUTEX_DESTROY(&classify_ptr->tcam_lock);
+
+ /* free data structures, based on HW type */
+ if (nxgep->niu_type == NEPTUNE) {
+ MUTEX_DESTROY(&classify_ptr->fcram_lock);
+ for (partition = 0; partition < MAX_PARTITION; partition++) {
+ MUTEX_DESTROY(&classify_ptr->hash_lock[partition]);
+ }
+ }
+ if (nxgep->drv_state & STATE_MDIO_LOCK_INIT) {
+ if (nxge_mdio_lock_init == 1) {
+ MUTEX_DESTROY(&nxge_mdio_lock);
+ }
+ atomic_add_32(&nxge_mdio_lock_init, -1);
+ }
+ if (nxgep->drv_state & STATE_MII_LOCK_INIT) {
+ if (nxge_mii_lock_init == 1) {
+ MUTEX_DESTROY(&nxge_mii_lock);
+ }
+ atomic_add_32(&nxge_mii_lock_init, -1);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes"));
+}
+
+nxge_status_t
+nxge_init(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init"));
+
+ /*
+ * Allocate system memory for the receive/transmit buffer blocks
+ * and receive/transmit descriptor rings.
+ */
+ status = nxge_alloc_mem_pool(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n"));
+ goto nxge_init_fail1;
+ }
+
+ /*
+ * Initialize and enable TXC registers
+ * (Globally enable TX controller,
+ * enable a port, configure dma channel bitmap,
+ * configure the max burst size).
+ */
+ status = nxge_txc_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txc failed\n"));
+ goto nxge_init_fail2;
+ }
+
+ /*
+ * Initialize and enable TXDMA channels.
+ */
+ status = nxge_init_txdma_channels(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n"));
+ goto nxge_init_fail3;
+ }
+
+ /*
+ * Initialize and enable RXDMA channels.
+ */
+ status = nxge_init_rxdma_channels(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n"));
+ goto nxge_init_fail4;
+ }
+
+ /*
+ * Initialize TCAM and FCRAM (Neptune).
+ */
+ status = nxge_classify_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n"));
+ goto nxge_init_fail5;
+ }
+
+ /*
+ * Initialize ZCP
+ */
+ status = nxge_zcp_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n"));
+ goto nxge_init_fail5;
+ }
+
+ /*
+ * Initialize IPP.
+ */
+ status = nxge_ipp_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n"));
+ goto nxge_init_fail5;
+ }
+
+ /*
+ * Initialize the MAC block.
+ */
+ status = nxge_mac_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n"));
+ goto nxge_init_fail5;
+ }
+
+ nxge_intrs_enable(nxgep);
+
+ /*
+ * Enable hardware interrupts.
+ */
+ nxge_intr_hw_enable(nxgep);
+ nxgep->drv_state |= STATE_HW_INITIALIZED;
+
+ goto nxge_init_exit;
+
+nxge_init_fail5:
+ nxge_uninit_rxdma_channels(nxgep);
+nxge_init_fail4:
+ nxge_uninit_txdma_channels(nxgep);
+nxge_init_fail3:
+ (void) nxge_txc_uninit(nxgep);
+nxge_init_fail2:
+ nxge_free_mem_pool(nxgep);
+nxge_init_fail1:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init status (failed) = 0x%08x", status));
+ return (status);
+
+nxge_init_exit:
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x",
+ status));
+ return (status);
+}
+
+
+timeout_id_t
+nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec)
+{
+ if ((nxgep->suspended == 0) ||
+ (nxgep->suspended == DDI_RESUME)) {
+ return (timeout(func, (caddr_t)nxgep,
+ drv_usectohz(1000 * msec)));
+ }
+ return (NULL);
+}
+
+/*ARGSUSED*/
+void
+nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid)
+{
+ if (timerid) {
+ (void) untimeout(timerid);
+ }
+}
+
+void
+nxge_uninit(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit"));
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_uninit: not initialized"));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_uninit"));
+ return;
+ }
+
+ /* stop timer */
+ if (nxgep->nxge_timerid) {
+ nxge_stop_timer(nxgep, nxgep->nxge_timerid);
+ nxgep->nxge_timerid = 0;
+ }
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_intr_hw_disable(nxgep);
+
+ /*
+ * Reset the receive MAC side.
+ */
+ (void) nxge_rx_mac_disable(nxgep);
+
+ /* Disable and soft reset the IPP */
+ (void) nxge_ipp_disable(nxgep);
+
+ /*
+ * Reset the transmit/receive DMA side.
+ */
+ (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
+ (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
+
+ nxge_uninit_txdma_channels(nxgep);
+ nxge_uninit_rxdma_channels(nxgep);
+
+ /*
+ * Reset the transmit MAC side.
+ */
+ (void) nxge_tx_mac_disable(nxgep);
+
+ nxge_free_mem_pool(nxgep);
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+
+ nxgep->drv_state &= ~STATE_HW_INITIALIZED;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: "
+ "nxge_mblks_pending %d", nxge_mblks_pending));
+}
+
+void
+nxge_get64(p_nxge_t nxgep, p_mblk_t mp)
+{
+ uint64_t reg;
+ uint64_t regdata;
+ int i, retry;
+
+ bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
+ regdata = 0;
+ retry = 1;
+
+ for (i = 0; i < retry; i++) {
+ NXGE_REG_RD64(nxgep->npi_handle, reg, &regdata);
+ }
+ bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
+}
+
+void
+nxge_put64(p_nxge_t nxgep, p_mblk_t mp)
+{
+ uint64_t reg;
+ uint64_t buf[2];
+
+ bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
+ reg = buf[0];
+
+ NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]);
+}
+
+
+nxge_os_mutex_t nxgedebuglock;
+int nxge_debug_init = 0;
+
+/*ARGSUSED*/
+/*VARARGS*/
+void
+nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...)
+{
+ char msg_buffer[1048];
+ char prefix_buffer[32];
+ int instance;
+ uint64_t debug_level;
+ int cmn_level = CE_CONT;
+ va_list ap;
+
+ debug_level = (nxgep == NULL) ? nxge_debug_level :
+ nxgep->nxge_debug_level;
+
+ if ((level & debug_level) ||
+ (level == NXGE_NOTE) ||
+ (level == NXGE_ERR_CTL)) {
+ /* do the msg processing */
+ if (nxge_debug_init == 0) {
+ MUTEX_INIT(&nxgedebuglock, NULL, MUTEX_DRIVER, NULL);
+ nxge_debug_init = 1;
+ }
+
+ MUTEX_ENTER(&nxgedebuglock);
+
+ if ((level & NXGE_NOTE)) {
+ cmn_level = CE_NOTE;
+ }
+
+ if (level & NXGE_ERR_CTL) {
+ cmn_level = CE_WARN;
+ }
+
+ va_start(ap, fmt);
+ (void) vsprintf(msg_buffer, fmt, ap);
+ va_end(ap);
+ if (nxgep == NULL) {
+ instance = -1;
+ (void) sprintf(prefix_buffer, "%s :", "nxge");
+ } else {
+ instance = nxgep->instance;
+ (void) sprintf(prefix_buffer,
+ "%s%d :", "nxge", instance);
+ }
+
+ MUTEX_EXIT(&nxgedebuglock);
+ cmn_err(cmn_level, "!%s %s\n",
+ prefix_buffer, msg_buffer);
+
+ }
+}
+
+char *
+nxge_dump_packet(char *addr, int size)
+{
+ uchar_t *ap = (uchar_t *)addr;
+ int i;
+ static char etherbuf[1024];
+ char *cp = etherbuf;
+ char digits[] = "0123456789abcdef";
+
+ if (!size)
+ size = 60;
+
+ if (size > MAX_DUMP_SZ) {
+ /* Dump the leading bytes */
+ for (i = 0; i < MAX_DUMP_SZ/2; i++) {
+ if (*ap > 0x0f)
+ *cp++ = digits[*ap >> 4];
+ *cp++ = digits[*ap++ & 0xf];
+ *cp++ = ':';
+ }
+ for (i = 0; i < 20; i++)
+ *cp++ = '.';
+ /* Dump the last MAX_DUMP_SZ/2 bytes */
+ ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2));
+ for (i = 0; i < MAX_DUMP_SZ/2; i++) {
+ if (*ap > 0x0f)
+ *cp++ = digits[*ap >> 4];
+ *cp++ = digits[*ap++ & 0xf];
+ *cp++ = ':';
+ }
+ } else {
+ for (i = 0; i < size; i++) {
+ if (*ap > 0x0f)
+ *cp++ = digits[*ap >> 4];
+ *cp++ = digits[*ap++ & 0xf];
+ *cp++ = ':';
+ }
+ }
+ *--cp = 0;
+ return (etherbuf);
+}
+
+#ifdef NXGE_DEBUG
+static void
+nxge_test_map_regs(p_nxge_t nxgep)
+{
+ ddi_acc_handle_t cfg_handle;
+ p_pci_cfg_t cfg_ptr;
+ ddi_acc_handle_t dev_handle;
+ char *dev_ptr;
+ ddi_acc_handle_t pci_config_handle;
+ uint32_t regval;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs"));
+
+ dev_handle = nxgep->dev_regs->nxge_regh;
+ dev_ptr = (char *)nxgep->dev_regs->nxge_regp;
+
+ if (nxgep->niu_type == NEPTUNE) {
+ cfg_handle = nxgep->dev_regs->nxge_pciregh;
+ cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "Neptune PCI cfg_ptr vendor id ptr 0x%llx",
+ &cfg_ptr->vendorid));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "\tvendorid 0x%x devid 0x%x",
+ NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0),
+ NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0)));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "PCI BAR: base 0x%x base14 0x%x base 18 0x%x "
+ "bar1c 0x%x",
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0)));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "\nNeptune PCI BAR: base20 0x%x base24 0x%x "
+ "base 28 0x%x bar2c 0x%x\n",
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0),
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0)));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "\nNeptune PCI BAR: base30 0x%x\n",
+ NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0)));
+
+ cfg_handle = nxgep->dev_regs->nxge_pciregh;
+ cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "first 0x%llx second 0x%llx third 0x%llx "
+ "last 0x%llx ",
+ NXGE_PIO_READ64(dev_handle,
+ (uint64_t *)(dev_ptr + 0), 0),
+ NXGE_PIO_READ64(dev_handle,
+ (uint64_t *)(dev_ptr + 8), 0),
+ NXGE_PIO_READ64(dev_handle,
+ (uint64_t *)(dev_ptr + 16), 0),
+ NXGE_PIO_READ64(cfg_handle,
+ (uint64_t *)(dev_ptr + 24), 0)));
+ }
+}
+
+#endif
+
+static void
+nxge_suspend(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend"));
+
+ nxge_intrs_disable(nxgep);
+ nxge_destroy_dev(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend"));
+}
+
+static nxge_status_t
+nxge_resume(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume"));
+ nxgep->suspended = DDI_RESUME;
+
+ nxge_global_reset(nxgep);
+ nxgep->suspended = 0;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_resume status = 0x%x", status));
+ return (status);
+}
+
+static nxge_status_t
+nxge_setup_dev(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d",
+ nxgep->mac.portnum));
+
+ status = nxge_xcvr_find(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_setup_dev status "
+ " (xcvr find 0x%08x)", status));
+ goto nxge_setup_dev_exit;
+ }
+
+ status = nxge_link_init(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_setup_dev status "
+ "(xcvr init 0x%08x)", status));
+ goto nxge_setup_dev_exit;
+ }
+
+nxge_setup_dev_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_setup_dev port %d status = 0x%08x",
+ nxgep->mac.portnum, status));
+
+ return (status);
+}
+
+static void
+nxge_destroy_dev(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev"));
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+
+ (void) nxge_hw_stop(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev"));
+}
+
+static nxge_status_t
+nxge_setup_system_dma_pages(p_nxge_t nxgep)
+{
+ int ddi_status = DDI_SUCCESS;
+ uint_t count;
+ ddi_dma_cookie_t cookie;
+ uint_t iommu_pagesize;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages"));
+ nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1);
+ if (nxgep->niu_type != N2_NIU) {
+ iommu_pagesize = dvma_pagesize(nxgep->dip);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
+ " default_block_size %d iommu_pagesize %d",
+ nxgep->sys_page_sz,
+ ddi_ptob(nxgep->dip, (ulong_t)1),
+ nxgep->rx_default_block_size,
+ iommu_pagesize));
+
+ if (iommu_pagesize != 0) {
+ if (nxgep->sys_page_sz == iommu_pagesize) {
+ if (iommu_pagesize > 0x4000)
+ nxgep->sys_page_sz = 0x4000;
+ } else {
+ if (nxgep->sys_page_sz > iommu_pagesize)
+ nxgep->sys_page_sz = iommu_pagesize;
+ }
+ }
+ }
+ nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
+ "default_block_size %d page mask %d",
+ nxgep->sys_page_sz,
+ ddi_ptob(nxgep->dip, (ulong_t)1),
+ nxgep->rx_default_block_size,
+ nxgep->sys_page_mask));
+
+
+ switch (nxgep->sys_page_sz) {
+ default:
+ nxgep->sys_page_sz = 0x1000;
+ nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
+ nxgep->rx_default_block_size = 0x1000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_4K;
+ break;
+ case 0x1000:
+ nxgep->rx_default_block_size = 0x1000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_4K;
+ break;
+ case 0x2000:
+ nxgep->rx_default_block_size = 0x2000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_8K;
+ break;
+ case 0x4000:
+ nxgep->rx_default_block_size = 0x4000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_16K;
+ break;
+ case 0x8000:
+ nxgep->rx_default_block_size = 0x8000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_32K;
+ break;
+ }
+
+#ifndef USE_RX_BIG_BUF
+ nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz;
+#else
+ nxgep->rx_default_block_size = 0x2000;
+ nxgep->rx_bksize_code = RBR_BKSIZE_8K;
+#endif
+ /*
+ * Get the system DMA burst size.
+ */
+ ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
+ DDI_DMA_DONTWAIT, 0,
+ &nxgep->dmasparehandle);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_dma_alloc_handle: failed "
+ " status 0x%x", ddi_status));
+ goto nxge_get_soft_properties_exit;
+ }
+
+ ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL,
+ (caddr_t)nxgep->dmasparehandle,
+ sizeof (nxgep->dmasparehandle),
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+ DDI_DMA_DONTWAIT, 0,
+ &cookie, &count);
+ if (ddi_status != DDI_DMA_MAPPED) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Binding spare handle to find system"
+ " burstsize failed."));
+ ddi_status = DDI_FAILURE;
+ goto nxge_get_soft_properties_fail1;
+ }
+
+ nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle);
+ (void) ddi_dma_unbind_handle(nxgep->dmasparehandle);
+
+nxge_get_soft_properties_fail1:
+ ddi_dma_free_handle(&nxgep->dmasparehandle);
+
+nxge_get_soft_properties_exit:
+
+ if (ddi_status != DDI_SUCCESS)
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_setup_system_dma_pages status = 0x%08x", status));
+ return (status);
+}
+
+static nxge_status_t
+nxge_alloc_mem_pool(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool"));
+
+ status = nxge_alloc_rx_mem_pool(nxgep);
+ if (status != NXGE_OK) {
+ return (NXGE_ERROR);
+ }
+
+ status = nxge_alloc_tx_mem_pool(nxgep);
+ if (status != NXGE_OK) {
+ nxge_free_rx_mem_pool(nxgep);
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_alloc_mem_pool"));
+ return (NXGE_OK);
+}
+
+static void
+nxge_free_mem_pool(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_mem_pool"));
+
+ nxge_free_rx_mem_pool(nxgep);
+ nxge_free_tx_mem_pool(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_mem_pool"));
+}
+
+static nxge_status_t
+nxge_alloc_rx_mem_pool(p_nxge_t nxgep)
+{
+ int i, j;
+ uint32_t ndmas, st_rdc;
+ p_nxge_dma_pt_cfg_t p_all_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_dma_pool_t dma_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_cntl_p;
+ size_t rx_buf_alloc_size;
+ size_t rx_cntl_alloc_size;
+ uint32_t *num_chunks; /* per dma */
+ nxge_status_t status = NXGE_OK;
+
+ uint32_t nxge_port_rbr_size;
+ uint32_t nxge_port_rbr_spare_size;
+ uint32_t nxge_port_rcr_size;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_mem_pool"));
+
+ p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
+ st_rdc = p_cfgp->start_rdc;
+ ndmas = p_cfgp->max_rdcs;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ " nxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas));
+
+ /*
+ * Allocate memory for each receive DMA channel.
+ */
+ dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
+ KM_SLEEP);
+ dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
+ sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
+
+ dma_cntl_poolp = (p_nxge_dma_pool_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
+ dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
+ sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
+
+ num_chunks = (uint32_t *)KMEM_ZALLOC(
+ sizeof (uint32_t) * ndmas, KM_SLEEP);
+
+ /*
+ * Assume that each DMA channel will be configured with default
+ * block size.
+ * rbr block counts are mod of batch count (16).
+ */
+ nxge_port_rbr_size = p_all_cfgp->rbr_size;
+ nxge_port_rcr_size = p_all_cfgp->rcr_size;
+
+ if (!nxge_port_rbr_size) {
+ nxge_port_rbr_size = NXGE_RBR_RBB_DEFAULT;
+ }
+ if (nxge_port_rbr_size % NXGE_RXDMA_POST_BATCH) {
+ nxge_port_rbr_size = (NXGE_RXDMA_POST_BATCH *
+ (nxge_port_rbr_size / NXGE_RXDMA_POST_BATCH + 1));
+ }
+
+ p_all_cfgp->rbr_size = nxge_port_rbr_size;
+ nxge_port_rbr_spare_size = nxge_rbr_spare_size;
+
+ if (nxge_port_rbr_spare_size % NXGE_RXDMA_POST_BATCH) {
+ nxge_port_rbr_spare_size = (NXGE_RXDMA_POST_BATCH *
+ (nxge_port_rbr_spare_size / NXGE_RXDMA_POST_BATCH + 1));
+ }
+
+ /*
+ * N2/NIU has limitation on the descriptor sizes (contiguous
+ * memory allocation on data buffers to 4M (contig_mem_alloc)
+ * and little endian for control buffers (must use the ddi/dki mem alloc
+ * function).
+ */
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (nxgep->niu_type == N2_NIU) {
+ nxge_port_rbr_spare_size = 0;
+ if ((nxge_port_rbr_size > NXGE_NIU_CONTIG_RBR_MAX) ||
+ (!ISP2(nxge_port_rbr_size))) {
+ nxge_port_rbr_size = NXGE_NIU_CONTIG_RBR_MAX;
+ }
+ if ((nxge_port_rcr_size > NXGE_NIU_CONTIG_RCR_MAX) ||
+ (!ISP2(nxge_port_rcr_size))) {
+ nxge_port_rcr_size = NXGE_NIU_CONTIG_RCR_MAX;
+ }
+ }
+#endif
+
+ rx_buf_alloc_size = (nxgep->rx_default_block_size *
+ (nxge_port_rbr_size + nxge_port_rbr_spare_size));
+
+ /*
+ * Addresses of receive block ring, receive completion ring and the
+ * mailbox must be all cache-aligned (64 bytes).
+ */
+ rx_cntl_alloc_size = nxge_port_rbr_size + nxge_port_rbr_spare_size;
+ rx_cntl_alloc_size *= (sizeof (rx_desc_t));
+ rx_cntl_alloc_size += (sizeof (rcr_entry_t) * nxge_port_rcr_size);
+ rx_cntl_alloc_size += sizeof (rxdma_mailbox_t);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_alloc_rx_mem_pool: "
+ "nxge_port_rbr_size = %d nxge_port_rbr_spare_size = %d "
+ "nxge_port_rcr_size = %d "
+ "rx_cntl_alloc_size = %d",
+ nxge_port_rbr_size, nxge_port_rbr_spare_size,
+ nxge_port_rcr_size,
+ rx_cntl_alloc_size));
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (nxgep->niu_type == N2_NIU) {
+ if (!ISP2(rx_buf_alloc_size)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_alloc_rx_mem_pool: "
+ " must be power of 2"));
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+ goto nxge_alloc_rx_mem_pool_exit;
+ }
+
+ if (rx_buf_alloc_size > (1 << 22)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_alloc_rx_mem_pool: "
+ " limit size to 4M"));
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+ goto nxge_alloc_rx_mem_pool_exit;
+ }
+
+ if (rx_cntl_alloc_size < 0x2000) {
+ rx_cntl_alloc_size = 0x2000;
+ }
+ }
+#endif
+ nxgep->nxge_port_rbr_size = nxge_port_rbr_size;
+ nxgep->nxge_port_rcr_size = nxge_port_rcr_size;
+
+ /*
+ * Allocate memory for receive buffers and descriptor rings.
+ * Replace allocation functions with interface functions provided
+ * by the partition manager when it is available.
+ */
+ /*
+ * Allocate memory for the receive buffer blocks.
+ */
+ for (i = 0; i < ndmas; i++) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_alloc_rx_mem_pool to alloc mem: "
+ " dma %d dma_buf_p %llx &dma_buf_p %llx",
+ i, dma_buf_p[i], &dma_buf_p[i]));
+ num_chunks[i] = 0;
+ status = nxge_alloc_rx_buf_dma(nxgep, st_rdc, &dma_buf_p[i],
+ rx_buf_alloc_size,
+ nxgep->rx_default_block_size, &num_chunks[i]);
+ if (status != NXGE_OK) {
+ break;
+ }
+ st_rdc++;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_alloc_rx_mem_pool DONE alloc mem: "
+ "dma %d dma_buf_p %llx &dma_buf_p %llx", i,
+ dma_buf_p[i], &dma_buf_p[i]));
+ }
+ if (i < ndmas) {
+ goto nxge_alloc_rx_mem_fail1;
+ }
+ /*
+ * Allocate memory for descriptor rings and mailbox.
+ */
+ st_rdc = p_cfgp->start_rdc;
+ for (j = 0; j < ndmas; j++) {
+ status = nxge_alloc_rx_cntl_dma(nxgep, st_rdc, &dma_cntl_p[j],
+ rx_cntl_alloc_size);
+ if (status != NXGE_OK) {
+ break;
+ }
+ st_rdc++;
+ }
+ if (j < ndmas) {
+ goto nxge_alloc_rx_mem_fail2;
+ }
+
+ dma_poolp->ndmas = ndmas;
+ dma_poolp->num_chunks = num_chunks;
+ dma_poolp->buf_allocated = B_TRUE;
+ nxgep->rx_buf_pool_p = dma_poolp;
+ dma_poolp->dma_buf_pool_p = dma_buf_p;
+
+ dma_cntl_poolp->ndmas = ndmas;
+ dma_cntl_poolp->buf_allocated = B_TRUE;
+ nxgep->rx_cntl_pool_p = dma_cntl_poolp;
+ dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
+
+ goto nxge_alloc_rx_mem_pool_exit;
+
+nxge_alloc_rx_mem_fail2:
+ /* Free control buffers */
+ j--;
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_rx_mem_pool: freeing control bufs (%d)", j));
+ for (; j >= 0; j--) {
+ nxge_free_rx_cntl_dma(nxgep,
+ (p_nxge_dma_common_t)dma_cntl_p[i]);
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)",
+ j));
+ }
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_rx_mem_pool: control bufs freed (%d)", j));
+
+nxge_alloc_rx_mem_fail1:
+ /* Free data buffers */
+ i--;
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_rx_mem_pool: freeing data bufs (%d)", i));
+ for (; i >= 0; i--) {
+ nxge_free_rx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i],
+ num_chunks[i]);
+ }
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_rx_mem_pool: data bufs freed (%d)", i));
+
+ KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
+ KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
+
+nxge_alloc_rx_mem_pool_exit:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_alloc_rx_mem_pool:status 0x%08x", status));
+
+ return (status);
+}
+
+static void
+nxge_free_rx_mem_pool(p_nxge_t nxgep)
+{
+ uint32_t i, ndmas;
+ p_nxge_dma_pool_t dma_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_cntl_p;
+ uint32_t *num_chunks;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_mem_pool"));
+
+ dma_poolp = nxgep->rx_buf_pool_p;
+ if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_free_rx_mem_pool "
+ "(null rx buf pool or buf not allocated"));
+ return;
+ }
+
+ dma_cntl_poolp = nxgep->rx_cntl_pool_p;
+ if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_free_rx_mem_pool "
+ "(null rx cntl buf pool or cntl buf not allocated"));
+ return;
+ }
+
+ dma_buf_p = dma_poolp->dma_buf_pool_p;
+ num_chunks = dma_poolp->num_chunks;
+
+ dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
+ ndmas = dma_cntl_poolp->ndmas;
+
+ for (i = 0; i < ndmas; i++) {
+ nxge_free_rx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]);
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ nxge_free_rx_cntl_dma(nxgep, dma_cntl_p[i]);
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ KMEM_FREE(dma_buf_p[i],
+ sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
+ KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t));
+ }
+
+ KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
+ KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
+
+ nxgep->rx_buf_pool_p = NULL;
+ nxgep->rx_cntl_pool_p = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_free_rx_mem_pool"));
+}
+
+
+static nxge_status_t
+nxge_alloc_rx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dmap,
+ size_t alloc_size, size_t block_size, uint32_t *num_chunks)
+{
+ p_nxge_dma_common_t rx_dmap;
+ nxge_status_t status = NXGE_OK;
+ size_t total_alloc_size;
+ size_t allocated = 0;
+ int i, size_index, array_size;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_buf_dma"));
+
+ rx_dmap = (p_nxge_dma_common_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
+ KM_SLEEP);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ",
+ dma_channel, alloc_size, block_size, dmap));
+
+ total_alloc_size = alloc_size;
+
+#if defined(RX_USE_RECLAIM_POST)
+ total_alloc_size = alloc_size + alloc_size/4;
+#endif
+
+ i = 0;
+ size_index = 0;
+ array_size = sizeof (alloc_sizes)/sizeof (size_t);
+ while ((alloc_sizes[size_index] < alloc_size) &&
+ (size_index < array_size))
+ size_index++;
+ if (size_index >= array_size) {
+ size_index = array_size - 1;
+ }
+
+ while ((allocated < total_alloc_size) &&
+ (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
+ rx_dmap[i].dma_chunk_index = i;
+ rx_dmap[i].block_size = block_size;
+ rx_dmap[i].alength = alloc_sizes[size_index];
+ rx_dmap[i].orig_alength = rx_dmap[i].alength;
+ rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
+ rx_dmap[i].dma_channel = dma_channel;
+ rx_dmap[i].contig_alloc_type = B_FALSE;
+
+ /*
+ * N2/NIU: data buffers must be contiguous as the driver
+ * needs to call Hypervisor api to set up
+ * logical pages.
+ */
+ if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
+ rx_dmap[i].contig_alloc_type = B_TRUE;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x "
+ "i %d nblocks %d alength %d",
+ dma_channel, i, &rx_dmap[i], block_size,
+ i, rx_dmap[i].nblocks,
+ rx_dmap[i].alength));
+ status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
+ &nxge_rx_dma_attr,
+ rx_dmap[i].alength,
+ &nxge_dev_buf_dma_acc_attr,
+ DDI_DMA_READ | DDI_DMA_STREAMING,
+ (p_nxge_dma_common_t)(&rx_dmap[i]));
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_alloc_rx_buf_dma: Alloc Failed "));
+ size_index--;
+ } else {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ " alloc_rx_buf_dma allocated rdc %d "
+ "chunk %d size %x dvma %x bufp %llx ",
+ dma_channel, i, rx_dmap[i].alength,
+ rx_dmap[i].ioaddr_pp, &rx_dmap[i]));
+ i++;
+ allocated += alloc_sizes[size_index];
+ }
+ }
+
+
+ if (allocated < total_alloc_size) {
+ goto nxge_alloc_rx_mem_fail1;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ " alloc_rx_buf_dma rdc %d allocated %d chunks",
+ dma_channel, i));
+ *num_chunks = i;
+ *dmap = rx_dmap;
+
+ goto nxge_alloc_rx_mem_exit;
+
+nxge_alloc_rx_mem_fail1:
+ KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
+
+nxge_alloc_rx_mem_exit:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_alloc_rx_buf_dma status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_free_rx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
+ uint32_t num_chunks)
+{
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_free_rx_buf_dma: # of chunks %d", num_chunks));
+
+ for (i = 0; i < num_chunks; i++) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_free_rx_buf_dma: chunk %d dmap 0x%llx",
+ i, dmap));
+ nxge_dma_mem_free(dmap++);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_free_rx_buf_dma"));
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_alloc_rx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dmap, size_t size)
+{
+ p_nxge_dma_common_t rx_dmap;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_rx_cntl_dma"));
+
+ rx_dmap = (p_nxge_dma_common_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
+
+ rx_dmap->contig_alloc_type = B_FALSE;
+
+ status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
+ &nxge_desc_dma_attr,
+ size,
+ &nxge_dev_desc_dma_acc_attr,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+ rx_dmap);
+ if (status != NXGE_OK) {
+ goto nxge_alloc_rx_cntl_dma_fail1;
+ }
+
+ *dmap = rx_dmap;
+ goto nxge_alloc_rx_cntl_dma_exit;
+
+nxge_alloc_rx_cntl_dma_fail1:
+ KMEM_FREE(rx_dmap, sizeof (nxge_dma_common_t));
+
+nxge_alloc_rx_cntl_dma_exit:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_alloc_rx_cntl_dma status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_free_rx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
+{
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_rx_cntl_dma"));
+
+ nxge_dma_mem_free(dmap);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_rx_cntl_dma"));
+}
+
+static nxge_status_t
+nxge_alloc_tx_mem_pool(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ int i, j;
+ uint32_t ndmas, st_tdc;
+ p_nxge_dma_pt_cfg_t p_all_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_dma_pool_t dma_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_cntl_p;
+ size_t tx_buf_alloc_size;
+ size_t tx_cntl_alloc_size;
+ uint32_t *num_chunks; /* per dma */
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool"));
+
+ p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
+ st_tdc = p_cfgp->start_tdc;
+ ndmas = p_cfgp->max_tdcs;
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool: "
+ "p_cfgp 0x%016llx start_tdc %d ndmas %d nxgep->max_tdcs %d",
+ p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, nxgep->max_tdcs));
+ /*
+ * Allocate memory for each transmit DMA channel.
+ */
+ dma_poolp = (p_nxge_dma_pool_t)KMEM_ZALLOC(sizeof (nxge_dma_pool_t),
+ KM_SLEEP);
+ dma_buf_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
+ sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
+
+ dma_cntl_poolp = (p_nxge_dma_pool_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_pool_t), KM_SLEEP);
+ dma_cntl_p = (p_nxge_dma_common_t *)KMEM_ZALLOC(
+ sizeof (p_nxge_dma_common_t) * ndmas, KM_SLEEP);
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ /*
+ * N2/NIU has limitation on the descriptor sizes (contiguous
+ * memory allocation on data buffers to 4M (contig_mem_alloc)
+ * and little endian for control buffers (must use the ddi/dki mem alloc
+ * function). The transmit ring is limited to 8K (includes the
+ * mailbox).
+ */
+ if (nxgep->niu_type == N2_NIU) {
+ if ((nxge_tx_ring_size > NXGE_NIU_CONTIG_TX_MAX) ||
+ (!ISP2(nxge_tx_ring_size))) {
+ nxge_tx_ring_size = NXGE_NIU_CONTIG_TX_MAX;
+ }
+ }
+#endif
+
+ nxgep->nxge_port_tx_ring_size = nxge_tx_ring_size;
+
+ /*
+ * Assume that each DMA channel will be configured with default
+ * transmit bufer size for copying transmit data.
+ * (For packet payload over this limit, packets will not be
+ * copied.)
+ */
+ tx_buf_alloc_size = (nxge_bcopy_thresh * nxge_tx_ring_size);
+
+ /*
+ * Addresses of transmit descriptor ring and the
+ * mailbox must be all cache-aligned (64 bytes).
+ */
+ tx_cntl_alloc_size = nxge_tx_ring_size;
+ tx_cntl_alloc_size *= (sizeof (tx_desc_t));
+ tx_cntl_alloc_size += sizeof (txdma_mailbox_t);
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (nxgep->niu_type == N2_NIU) {
+ if (!ISP2(tx_buf_alloc_size)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_alloc_tx_mem_pool: "
+ " must be power of 2"));
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+ goto nxge_alloc_tx_mem_pool_exit;
+ }
+
+ if (tx_buf_alloc_size > (1 << 22)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_alloc_tx_mem_pool: "
+ " limit size to 4M"));
+ status |= (NXGE_ERROR | NXGE_DDI_FAILED);
+ goto nxge_alloc_tx_mem_pool_exit;
+ }
+
+ if (tx_cntl_alloc_size < 0x2000) {
+ tx_cntl_alloc_size = 0x2000;
+ }
+ }
+#endif
+
+ num_chunks = (uint32_t *)KMEM_ZALLOC(
+ sizeof (uint32_t) * ndmas, KM_SLEEP);
+
+ /*
+ * Allocate memory for transmit buffers and descriptor rings.
+ * Replace allocation functions with interface functions provided
+ * by the partition manager when it is available.
+ *
+ * Allocate memory for the transmit buffer pool.
+ */
+ for (i = 0; i < ndmas; i++) {
+ num_chunks[i] = 0;
+ status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i],
+ tx_buf_alloc_size,
+ nxge_bcopy_thresh, &num_chunks[i]);
+ if (status != NXGE_OK) {
+ break;
+ }
+ st_tdc++;
+ }
+ if (i < ndmas) {
+ goto nxge_alloc_tx_mem_pool_fail1;
+ }
+
+ st_tdc = p_cfgp->start_tdc;
+ /*
+ * Allocate memory for descriptor rings and mailbox.
+ */
+ for (j = 0; j < ndmas; j++) {
+ status = nxge_alloc_tx_cntl_dma(nxgep, st_tdc, &dma_cntl_p[j],
+ tx_cntl_alloc_size);
+ if (status != NXGE_OK) {
+ break;
+ }
+ st_tdc++;
+ }
+ if (j < ndmas) {
+ goto nxge_alloc_tx_mem_pool_fail2;
+ }
+
+ dma_poolp->ndmas = ndmas;
+ dma_poolp->num_chunks = num_chunks;
+ dma_poolp->buf_allocated = B_TRUE;
+ dma_poolp->dma_buf_pool_p = dma_buf_p;
+ nxgep->tx_buf_pool_p = dma_poolp;
+
+ dma_cntl_poolp->ndmas = ndmas;
+ dma_cntl_poolp->buf_allocated = B_TRUE;
+ dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p;
+ nxgep->tx_cntl_pool_p = dma_cntl_poolp;
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL,
+ "==> nxge_alloc_tx_mem_pool: start_tdc %d "
+ "ndmas %d poolp->ndmas %d",
+ st_tdc, ndmas, dma_poolp->ndmas));
+
+ goto nxge_alloc_tx_mem_pool_exit;
+
+nxge_alloc_tx_mem_pool_fail2:
+ /* Free control buffers */
+ j--;
+ for (; j >= 0; j--) {
+ nxge_free_tx_cntl_dma(nxgep,
+ (p_nxge_dma_common_t)dma_cntl_p[i]);
+ }
+
+nxge_alloc_tx_mem_pool_fail1:
+ /* Free data buffers */
+ i--;
+ for (; i >= 0; i--) {
+ nxge_free_tx_buf_dma(nxgep, (p_nxge_dma_common_t)dma_buf_p[i],
+ num_chunks[i]);
+ }
+
+ KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
+
+nxge_alloc_tx_mem_pool_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL,
+ "<== nxge_alloc_tx_mem_pool:status 0x%08x", status));
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_alloc_tx_buf_dma(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dmap, size_t alloc_size,
+ size_t block_size, uint32_t *num_chunks)
+{
+ p_nxge_dma_common_t tx_dmap;
+ nxge_status_t status = NXGE_OK;
+ size_t total_alloc_size;
+ size_t allocated = 0;
+ int i, size_index, array_size;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_buf_dma"));
+
+ tx_dmap = (p_nxge_dma_common_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK,
+ KM_SLEEP);
+
+ total_alloc_size = alloc_size;
+ i = 0;
+ size_index = 0;
+ array_size = sizeof (alloc_sizes) / sizeof (size_t);
+ while ((alloc_sizes[size_index] < alloc_size) &&
+ (size_index < array_size))
+ size_index++;
+ if (size_index >= array_size) {
+ size_index = array_size - 1;
+ }
+
+ while ((allocated < total_alloc_size) &&
+ (size_index >= 0) && (i < NXGE_DMA_BLOCK)) {
+
+ tx_dmap[i].dma_chunk_index = i;
+ tx_dmap[i].block_size = block_size;
+ tx_dmap[i].alength = alloc_sizes[size_index];
+ tx_dmap[i].orig_alength = tx_dmap[i].alength;
+ tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size;
+ tx_dmap[i].dma_channel = dma_channel;
+ tx_dmap[i].contig_alloc_type = B_FALSE;
+
+ /*
+ * N2/NIU: data buffers must be contiguous as the driver
+ * needs to call Hypervisor api to set up
+ * logical pages.
+ */
+ if ((nxgep->niu_type == N2_NIU) && (NXGE_DMA_BLOCK == 1)) {
+ tx_dmap[i].contig_alloc_type = B_TRUE;
+ }
+
+ status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
+ &nxge_tx_dma_attr,
+ tx_dmap[i].alength,
+ &nxge_dev_buf_dma_acc_attr,
+ DDI_DMA_WRITE | DDI_DMA_STREAMING,
+ (p_nxge_dma_common_t)(&tx_dmap[i]));
+ if (status != NXGE_OK) {
+ size_index--;
+ } else {
+ i++;
+ allocated += alloc_sizes[size_index];
+ }
+ }
+
+ if (allocated < total_alloc_size) {
+ goto nxge_alloc_tx_mem_fail1;
+ }
+
+ *num_chunks = i;
+ *dmap = tx_dmap;
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d",
+ *dmap, i));
+ goto nxge_alloc_tx_mem_exit;
+
+nxge_alloc_tx_mem_fail1:
+ KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
+
+nxge_alloc_tx_mem_exit:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_alloc_tx_buf_dma status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_free_tx_buf_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap,
+ uint32_t num_chunks)
+{
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_free_tx_buf_dma"));
+
+ for (i = 0; i < num_chunks; i++) {
+ nxge_dma_mem_free(dmap++);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM_CTL, "<== nxge_free_tx_buf_dma"));
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_alloc_tx_cntl_dma(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dmap, size_t size)
+{
+ p_nxge_dma_common_t tx_dmap;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_alloc_tx_cntl_dma"));
+ tx_dmap = (p_nxge_dma_common_t)
+ KMEM_ZALLOC(sizeof (nxge_dma_common_t), KM_SLEEP);
+
+ tx_dmap->contig_alloc_type = B_FALSE;
+
+ status = nxge_dma_mem_alloc(nxgep, nxge_force_dma,
+ &nxge_desc_dma_attr,
+ size,
+ &nxge_dev_desc_dma_acc_attr,
+ DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+ tx_dmap);
+ if (status != NXGE_OK) {
+ goto nxge_alloc_tx_cntl_dma_fail1;
+ }
+
+ *dmap = tx_dmap;
+ goto nxge_alloc_tx_cntl_dma_exit;
+
+nxge_alloc_tx_cntl_dma_fail1:
+ KMEM_FREE(tx_dmap, sizeof (nxge_dma_common_t));
+
+nxge_alloc_tx_cntl_dma_exit:
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_alloc_tx_cntl_dma status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_free_tx_cntl_dma(p_nxge_t nxgep, p_nxge_dma_common_t dmap)
+{
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_free_tx_cntl_dma"));
+
+ nxge_dma_mem_free(dmap);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_free_tx_cntl_dma"));
+}
+
+static void
+nxge_free_tx_mem_pool(p_nxge_t nxgep)
+{
+ uint32_t i, ndmas;
+ p_nxge_dma_pool_t dma_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_cntl_p;
+ uint32_t *num_chunks;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_free_tx_mem_pool"));
+
+ dma_poolp = nxgep->tx_buf_pool_p;
+ if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_free_tx_mem_pool "
+ "(null rx buf pool or buf not allocated"));
+ return;
+ }
+
+ dma_cntl_poolp = nxgep->tx_cntl_pool_p;
+ if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_free_tx_mem_pool "
+ "(null tx cntl buf pool or cntl buf not allocated"));
+ return;
+ }
+
+ dma_buf_p = dma_poolp->dma_buf_pool_p;
+ num_chunks = dma_poolp->num_chunks;
+
+ dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
+ ndmas = dma_cntl_poolp->ndmas;
+
+ for (i = 0; i < ndmas; i++) {
+ nxge_free_tx_buf_dma(nxgep, dma_buf_p[i], num_chunks[i]);
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ nxge_free_tx_cntl_dma(nxgep, dma_cntl_p[i]);
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ KMEM_FREE(dma_buf_p[i],
+ sizeof (nxge_dma_common_t) * NXGE_DMA_BLOCK);
+ KMEM_FREE(dma_cntl_p[i], sizeof (nxge_dma_common_t));
+ }
+
+ KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas);
+ KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_cntl_poolp, sizeof (nxge_dma_pool_t));
+ KMEM_FREE(dma_buf_p, ndmas * sizeof (p_nxge_dma_common_t));
+ KMEM_FREE(dma_poolp, sizeof (nxge_dma_pool_t));
+
+ nxgep->tx_buf_pool_p = NULL;
+ nxgep->tx_cntl_pool_p = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_free_tx_mem_pool"));
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_dma_mem_alloc(p_nxge_t nxgep, dma_method_t method,
+ struct ddi_dma_attr *dma_attrp,
+ size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags,
+ p_nxge_dma_common_t dma_p)
+{
+ caddr_t kaddrp;
+ int ddi_status = DDI_SUCCESS;
+ boolean_t contig_alloc_type;
+
+ contig_alloc_type = dma_p->contig_alloc_type;
+
+ if (contig_alloc_type && (nxgep->niu_type != N2_NIU)) {
+ /*
+ * contig_alloc_type for contiguous memory only allowed
+ * for N2/NIU.
+ */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc: alloc type not allows (%d)",
+ dma_p->contig_alloc_type));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ dma_p->dma_handle = NULL;
+ dma_p->acc_handle = NULL;
+ dma_p->kaddrp = dma_p->last_kaddrp = NULL;
+ dma_p->first_ioaddr_pp = dma_p->last_ioaddr_pp = NULL;
+ ddi_status = ddi_dma_alloc_handle(nxgep->dip, dma_attrp,
+ DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:ddi_dma_alloc_handle failed."));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ switch (contig_alloc_type) {
+ case B_FALSE:
+ ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length,
+ acc_attr_p,
+ xfer_flags,
+ DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength,
+ &dma_p->acc_handle);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:ddi_dma_mem_alloc failed"));
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ dma_p->dma_handle = NULL;
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+ if (dma_p->alength < length) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:ddi_dma_mem_alloc "
+ "< length."));
+ ddi_dma_mem_free(&dma_p->acc_handle);
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ dma_p->acc_handle = NULL;
+ dma_p->dma_handle = NULL;
+ return (NXGE_ERROR);
+ }
+
+ ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
+ kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
+ &dma_p->dma_cookie, &dma_p->ncookies);
+ if (ddi_status != DDI_DMA_MAPPED) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:di_dma_addr_bind failed "
+ "(staus 0x%x ncookies %d.)", ddi_status,
+ dma_p->ncookies));
+ if (dma_p->acc_handle) {
+ ddi_dma_mem_free(&dma_p->acc_handle);
+ dma_p->acc_handle = NULL;
+ }
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ dma_p->dma_handle = NULL;
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ if (dma_p->ncookies != 1) {
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "nxge_dma_mem_alloc:ddi_dma_addr_bind "
+ "> 1 cookie"
+ "(staus 0x%x ncookies %d.)", ddi_status,
+ dma_p->ncookies));
+ if (dma_p->acc_handle) {
+ ddi_dma_mem_free(&dma_p->acc_handle);
+ dma_p->acc_handle = NULL;
+ }
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ dma_p->dma_handle = NULL;
+ return (NXGE_ERROR);
+ }
+ break;
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ case B_TRUE:
+ kaddrp = (caddr_t)contig_mem_alloc(length);
+ if (kaddrp == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:contig_mem_alloc failed."));
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ dma_p->alength = length;
+ ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL,
+ kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0,
+ &dma_p->dma_cookie, &dma_p->ncookies);
+ if (ddi_status != DDI_DMA_MAPPED) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:di_dma_addr_bind failed "
+ "(status 0x%x ncookies %d.)", ddi_status,
+ dma_p->ncookies));
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_dma_mem_alloc: (not mapped)"
+ "length %lu (0x%x) "
+ "free contig kaddrp $%p "
+ "va_to_pa $%p",
+ length, length,
+ kaddrp,
+ va_to_pa(kaddrp)));
+
+
+ contig_mem_free((void *)kaddrp, length);
+ ddi_dma_free_handle(&dma_p->dma_handle);
+
+ dma_p->dma_handle = NULL;
+ dma_p->acc_handle = NULL;
+ dma_p->alength = NULL;
+ dma_p->kaddrp = NULL;
+
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ if (dma_p->ncookies != 1 ||
+ (dma_p->dma_cookie.dmac_laddress == NULL)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc:di_dma_addr_bind > 1 "
+ "cookie or "
+ "dmac_laddress is NULL $%p size %d "
+ " (status 0x%x ncookies %d.)",
+ ddi_status,
+ dma_p->dma_cookie.dmac_laddress,
+ dma_p->dma_cookie.dmac_size,
+ dma_p->ncookies));
+
+ contig_mem_free((void *)kaddrp, length);
+ ddi_dma_free_handle(&dma_p->dma_handle);
+
+ dma_p->alength = 0;
+ dma_p->dma_handle = NULL;
+ dma_p->acc_handle = NULL;
+ dma_p->kaddrp = NULL;
+
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+ break;
+
+#else
+ case B_TRUE:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_dma_mem_alloc: invalid alloc type for !sun4v"));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+#endif
+ }
+
+ dma_p->kaddrp = kaddrp;
+ dma_p->last_kaddrp = (unsigned char *)kaddrp +
+ dma_p->alength - RXBUF_64B_ALIGNED;
+ dma_p->ioaddr_pp = (unsigned char *)dma_p->dma_cookie.dmac_laddress;
+ dma_p->last_ioaddr_pp =
+ (unsigned char *)dma_p->dma_cookie.dmac_laddress +
+ dma_p->alength - RXBUF_64B_ALIGNED;
+
+ NPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle);
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ dma_p->orig_ioaddr_pp =
+ (unsigned char *)dma_p->dma_cookie.dmac_laddress;
+ dma_p->orig_alength = length;
+ dma_p->orig_kaddrp = kaddrp;
+ dma_p->orig_vatopa = (uint64_t)va_to_pa(kaddrp);
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dma_mem_alloc: "
+ "dma buffer allocated: dma_p $%p "
+ "return dmac_ladress from cookie $%p cookie dmac_size %d "
+ "dma_p->ioaddr_p $%p "
+ "dma_p->orig_ioaddr_p $%p "
+ "orig_vatopa $%p "
+ "alength %d (0x%x) "
+ "kaddrp $%p "
+ "length %d (0x%x)",
+ dma_p,
+ dma_p->dma_cookie.dmac_laddress, dma_p->dma_cookie.dmac_size,
+ dma_p->ioaddr_pp,
+ dma_p->orig_ioaddr_pp,
+ dma_p->orig_vatopa,
+ dma_p->alength, dma_p->alength,
+ kaddrp,
+ length, length));
+
+ return (NXGE_OK);
+}
+
+static void
+nxge_dma_mem_free(p_nxge_dma_common_t dma_p)
+{
+ if (dma_p->dma_handle != NULL) {
+ if (dma_p->ncookies) {
+ (void) ddi_dma_unbind_handle(dma_p->dma_handle);
+ dma_p->ncookies = 0;
+ }
+ ddi_dma_free_handle(&dma_p->dma_handle);
+ dma_p->dma_handle = NULL;
+ }
+
+ if (dma_p->acc_handle != NULL) {
+ ddi_dma_mem_free(&dma_p->acc_handle);
+ dma_p->acc_handle = NULL;
+ NPI_DMA_ACC_HANDLE_SET(dma_p, NULL);
+ }
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (dma_p->contig_alloc_type &&
+ dma_p->orig_kaddrp && dma_p->orig_alength) {
+ NXGE_DEBUG_MSG((NULL, DMA_CTL, "nxge_dma_mem_free: "
+ "kaddrp $%p (orig_kaddrp $%p)"
+ "mem type %d ",
+ "orig_alength %d "
+ "alength 0x%x (%d)",
+ dma_p->kaddrp,
+ dma_p->orig_kaddrp,
+ dma_p->contig_alloc_type,
+ dma_p->orig_alength,
+ dma_p->alength, dma_p->alength));
+
+ contig_mem_free(dma_p->orig_kaddrp, dma_p->orig_alength);
+ dma_p->orig_alength = NULL;
+ dma_p->orig_kaddrp = NULL;
+ dma_p->contig_alloc_type = B_FALSE;
+ }
+#endif
+ dma_p->kaddrp = NULL;
+ dma_p->alength = NULL;
+}
+
+/*
+ * nxge_m_start() -- start transmitting and receiving.
+ *
+ * This function is called by the MAC layer when the first
+ * stream is open to prepare the hardware ready for sending
+ * and transmitting packets.
+ */
+static int
+nxge_m_start(void *arg)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start"));
+
+ MUTEX_ENTER(nxgep->genlock);
+ if (nxgep->drv_state & STATE_HW_INITIALIZED) {
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
+ "<== nxge_m_start: hardware already initialized"));
+ MUTEX_EXIT(nxgep->genlock);
+ return (EINVAL);
+ }
+
+ if (nxge_init(nxgep) != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_start: initialization failed"));
+ MUTEX_EXIT(nxgep->genlock);
+ return (EIO);
+ }
+
+ /*
+ * Start timer to check the system error and tx hangs
+ */
+ nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state,
+ NXGE_CHECK_TIMER);
+
+ nxgep->nxge_mac_state = NXGE_MAC_STARTED;
+
+ MUTEX_EXIT(nxgep->genlock);
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_start"));
+
+ return (0);
+}
+
+/*
+ * nxge_m_stop(): stop transmitting and receiving.
+ */
+static void
+nxge_m_stop(void *arg)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_stop"));
+
+ MUTEX_ENTER(nxgep->genlock);
+
+ nxge_intrs_disable(nxgep);
+ if (nxgep->nxge_timerid) {
+ nxge_stop_timer(nxgep, nxgep->nxge_timerid);
+ nxgep->nxge_timerid = 0;
+ }
+ nxge_uninit(nxgep);
+
+ nxgep->nxge_mac_state = NXGE_MAC_STOPPED;
+
+ MUTEX_EXIT(nxgep->genlock);
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_stop"));
+}
+
+static int
+nxge_m_unicst(void *arg, const uint8_t *macaddr)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ struct ether_addr addrp;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_m_unicst"));
+
+ bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL);
+ if (nxge_set_mac_addr(nxgep, &addrp)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_unicst: set unitcast failed"));
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_unicst"));
+
+ return (0);
+}
+
+static int
+nxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ struct ether_addr addrp;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_m_multicst: add %d", add));
+
+ bcopy(mca, (uint8_t *)&addrp, ETHERADDRL);
+ if (add) {
+ if (nxge_add_mcast_addr(nxgep, &addrp)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_multicst: add multicast failed"));
+ return (EINVAL);
+ }
+ } else {
+ if (nxge_del_mcast_addr(nxgep, &addrp)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_multicst: del multicast failed"));
+ return (EINVAL);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_m_multicst"));
+
+ return (0);
+}
+
+static int
+nxge_m_promisc(void *arg, boolean_t on)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "==> nxge_m_promisc: on %d", on));
+
+ if (nxge_set_promisc(nxgep, on)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_promisc: set promisc failed"));
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MAC_CTL,
+ "<== nxge_m_promisc: on %d", on));
+
+ return (0);
+}
+
+static void
+nxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
+ boolean_t need_privilege;
+ int err;
+ int cmd;
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl"));
+
+ iocp = (struct iocblk *)mp->b_rptr;
+ iocp->ioc_error = 0;
+ need_privilege = B_TRUE;
+ cmd = iocp->ioc_cmd;
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_ioctl: cmd 0x%08x", cmd));
+ switch (cmd) {
+ default:
+ miocnak(wq, mp, 0, EINVAL);
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl: invalid"));
+ return;
+
+ case LB_GET_INFO_SIZE:
+ case LB_GET_INFO:
+ case LB_GET_MODE:
+ need_privilege = B_FALSE;
+ break;
+ case LB_SET_MODE:
+ break;
+
+ case ND_GET:
+ need_privilege = B_FALSE;
+ break;
+ case ND_SET:
+ break;
+
+ case NXGE_GET_MII:
+ case NXGE_PUT_MII:
+ case NXGE_GET64:
+ case NXGE_PUT64:
+ case NXGE_GET_TX_RING_SZ:
+ case NXGE_GET_TX_DESC:
+ case NXGE_TX_SIDE_RESET:
+ case NXGE_RX_SIDE_RESET:
+ case NXGE_GLOBAL_RESET:
+ case NXGE_RESET_MAC:
+ case NXGE_TX_REGS_DUMP:
+ case NXGE_RX_REGS_DUMP:
+ case NXGE_INT_REGS_DUMP:
+ case NXGE_VIR_INT_REGS_DUMP:
+ case NXGE_PUT_TCAM:
+ case NXGE_GET_TCAM:
+ case NXGE_RTRACE:
+ case NXGE_RDUMP:
+
+ need_privilege = B_FALSE;
+ break;
+ case NXGE_INJECT_ERR:
+ cmn_err(CE_NOTE, "!nxge_m_ioctl: Inject error\n");
+ nxge_err_inject(nxgep, wq, mp);
+ break;
+ }
+
+ if (need_privilege) {
+ if (secpolicy_net_config != NULL)
+ err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
+ else
+ err = drv_priv(iocp->ioc_cr);
+ if (err != 0) {
+ miocnak(wq, mp, 0, err);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_m_ioctl: no priv"));
+ return;
+ }
+ }
+
+ switch (cmd) {
+ case ND_GET:
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_GET command"));
+ case ND_SET:
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "ND_SET command"));
+ nxge_param_ioctl(nxgep, wq, mp, iocp);
+ break;
+
+ case LB_GET_MODE:
+ case LB_SET_MODE:
+ case LB_GET_INFO_SIZE:
+ case LB_GET_INFO:
+ nxge_loopback_ioctl(nxgep, wq, mp, iocp);
+ break;
+
+ case NXGE_GET_MII:
+ case NXGE_PUT_MII:
+ case NXGE_PUT_TCAM:
+ case NXGE_GET_TCAM:
+ case NXGE_GET64:
+ case NXGE_PUT64:
+ case NXGE_GET_TX_RING_SZ:
+ case NXGE_GET_TX_DESC:
+ case NXGE_TX_SIDE_RESET:
+ case NXGE_RX_SIDE_RESET:
+ case NXGE_GLOBAL_RESET:
+ case NXGE_RESET_MAC:
+ case NXGE_TX_REGS_DUMP:
+ case NXGE_RX_REGS_DUMP:
+ case NXGE_INT_REGS_DUMP:
+ case NXGE_VIR_INT_REGS_DUMP:
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
+ "==> nxge_m_ioctl: cmd 0x%x", cmd));
+ nxge_hw_ioctl(nxgep, wq, mp, iocp);
+ break;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "<== nxge_m_ioctl"));
+}
+
+extern void nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count);
+
+static void
+nxge_m_resources(void *arg)
+{
+ p_nxge_t nxgep = arg;
+ mac_rx_fifo_t mrf;
+ p_rx_rcr_rings_t rcr_rings;
+ p_rx_rcr_ring_t *rcr_p;
+ uint32_t i, ndmas;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_m_resources"));
+
+ MUTEX_ENTER(nxgep->genlock);
+ mrf.mrf_type = MAC_RX_FIFO;
+ mrf.mrf_blank = nxge_rx_hw_blank;
+ mrf.mrf_arg = (void *)nxgep;
+
+ mrf.mrf_normal_blank_time = 128;
+ mrf.mrf_normal_pkt_count = 8;
+ rcr_rings = nxgep->rx_rcr_rings;
+ rcr_p = rcr_rings->rcr_rings;
+ ndmas = rcr_rings->ndmas;
+
+ for (i = 0; i < ndmas; i++) {
+ ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle =
+ mac_resource_add(nxgep->mach,
+ (mac_resource_t *)&mrf);
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_CTL,
+ "==> nxge_m_resources: vdma %d dma %d "
+ "rcrptr 0x%016llx mac_handle 0x%016llx",
+ i, ((p_rx_rcr_ring_t)rcr_p[i])->rdc,
+ rcr_p[i],
+ ((p_rx_rcr_ring_t)rcr_p[i])->rcr_mac_handle));
+ }
+
+ MUTEX_EXIT(nxgep->genlock);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_m_resources"));
+}
+
+/*ARGSUSED*/
+static boolean_t
+nxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
+{
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM: {
+ uint32_t *txflags = cap_data;
+
+ *txflags = HCKSUM_INET_PARTIAL;
+ break;
+ }
+ case MAC_CAPAB_POLL:
+ /*
+ * There's nothing for us to fill in, simply returning
+ * B_TRUE stating that we support polling is sufficient.
+ */
+ break;
+
+ default:
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+/*
+ * Module loading and removing entry points.
+ */
+
+static struct cb_ops nxge_cb_ops = {
+ nodev, /* cb_open */
+ nodev, /* cb_close */
+ nodev, /* cb_strategy */
+ nodev, /* cb_print */
+ nodev, /* cb_dump */
+ nodev, /* cb_read */
+ nodev, /* cb_write */
+ nodev, /* cb_ioctl */
+ nodev, /* cb_devmap */
+ nodev, /* cb_mmap */
+ nodev, /* cb_segmap */
+ nochpoll, /* cb_chpoll */
+ ddi_prop_op, /* cb_prop_op */
+ NULL,
+ D_MP, /* cb_flag */
+ CB_REV, /* rev */
+ nodev, /* int (*cb_aread)() */
+ nodev /* int (*cb_awrite)() */
+};
+
+static struct dev_ops nxge_dev_ops = {
+ DEVO_REV, /* devo_rev */
+ 0, /* devo_refcnt */
+ nulldev,
+ nulldev, /* devo_identify */
+ nulldev, /* devo_probe */
+ nxge_attach, /* devo_attach */
+ nxge_detach, /* devo_detach */
+ nodev, /* devo_reset */
+ &nxge_cb_ops, /* devo_cb_ops */
+ (struct bus_ops *)NULL, /* devo_bus_ops */
+ ddi_power /* devo_power */
+};
+
+extern struct mod_ops mod_driverops;
+
+#define NXGE_DESC_VER "Sun NIU 10Gb Ethernet %I%"
+
+/*
+ * Module linkage information for the kernel.
+ */
+static struct modldrv nxge_modldrv = {
+ &mod_driverops,
+ NXGE_DESC_VER,
+ &nxge_dev_ops
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1, (void *) &nxge_modldrv, NULL
+};
+
+int
+_init(void)
+{
+ int status;
+
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init"));
+ mac_init_ops(&nxge_dev_ops, "nxge");
+ status = ddi_soft_state_init(&nxge_list, sizeof (nxge_t), 0);
+ if (status != 0) {
+ NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
+ "failed to init device soft state"));
+ goto _init_exit;
+ }
+
+ status = mod_install(&modlinkage);
+ if (status != 0) {
+ ddi_soft_state_fini(&nxge_list);
+ NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "Mod install failed"));
+ goto _init_exit;
+ }
+
+ MUTEX_INIT(&nxge_common_lock, NULL, MUTEX_DRIVER, NULL);
+
+_init_exit:
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status));
+
+ return (status);
+}
+
+int
+_fini(void)
+{
+ int status;
+
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini"));
+
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove"));
+ status = mod_remove(&modlinkage);
+ if (status != DDI_SUCCESS) {
+ NXGE_DEBUG_MSG((NULL, MOD_CTL,
+ "Module removal failed 0x%08x",
+ status));
+ goto _fini_exit;
+ }
+
+ mac_fini_ops(&nxge_dev_ops);
+
+ ddi_soft_state_fini(&nxge_list);
+
+ MUTEX_DESTROY(&nxge_common_lock);
+_fini_exit:
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status));
+
+ return (status);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ int status;
+
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info"));
+ status = mod_info(&modlinkage, modinfop);
+ NXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_add_intrs(p_nxge_t nxgep)
+{
+
+ int intr_types;
+ int type = 0;
+ int ddi_status = DDI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs"));
+
+ nxgep->nxge_intr_type.intr_registered = B_FALSE;
+ nxgep->nxge_intr_type.intr_enabled = B_FALSE;
+ nxgep->nxge_intr_type.msi_intx_cnt = 0;
+ nxgep->nxge_intr_type.intr_added = 0;
+ nxgep->nxge_intr_type.niu_msi_enable = B_FALSE;
+ nxgep->nxge_intr_type.intr_type = 0;
+
+ if (nxgep->niu_type == N2_NIU) {
+ nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
+ } else if (nxge_msi_enable) {
+ nxgep->nxge_intr_type.niu_msi_enable = B_TRUE;
+ }
+
+ /* Get the supported interrupt types */
+ if ((ddi_status = ddi_intr_get_supported_types(nxgep->dip, &intr_types))
+ != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_intrs: "
+ "ddi_intr_get_supported_types failed: status 0x%08x",
+ ddi_status));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+ nxgep->nxge_intr_type.intr_types = intr_types;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: 0x%08x", intr_types));
+
+ /*
+ * Solaris MSIX is not supported yet. use MSI for now.
+ * nxge_msi_enable (1):
+ * 1 - MSI 2 - MSI-X others - FIXED
+ */
+ switch (nxge_msi_enable) {
+ default:
+ type = DDI_INTR_TYPE_FIXED;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
+ "use fixed (intx emulation) type %08x",
+ type));
+ break;
+
+ case 2:
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: 0x%08x", intr_types));
+ if (intr_types & DDI_INTR_TYPE_MSIX) {
+ type = DDI_INTR_TYPE_MSIX;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSIX 0x%08x",
+ type));
+ } else if (intr_types & DDI_INTR_TYPE_MSI) {
+ type = DDI_INTR_TYPE_MSI;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSI 0x%08x",
+ type));
+ } else if (intr_types & DDI_INTR_TYPE_FIXED) {
+ type = DDI_INTR_TYPE_FIXED;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSXED0x%08x",
+ type));
+ }
+ break;
+
+ case 1:
+ if (intr_types & DDI_INTR_TYPE_MSI) {
+ type = DDI_INTR_TYPE_MSI;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSI 0x%08x",
+ type));
+ } else if (intr_types & DDI_INTR_TYPE_MSIX) {
+ type = DDI_INTR_TYPE_MSIX;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSIX 0x%08x",
+ type));
+ } else if (intr_types & DDI_INTR_TYPE_FIXED) {
+ type = DDI_INTR_TYPE_FIXED;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "ddi_intr_get_supported_types: MSXED0x%08x",
+ type));
+ }
+ }
+
+ nxgep->nxge_intr_type.intr_type = type;
+ if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI ||
+ type == DDI_INTR_TYPE_FIXED) &&
+ nxgep->nxge_intr_type.niu_msi_enable) {
+ if ((status = nxge_add_intrs_adv(nxgep)) != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_add_intrs: "
+ " nxge_add_intrs_adv failed: status 0x%08x",
+ status));
+ return (status);
+ } else {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs: "
+ "interrupts registered : type %d", type));
+ nxgep->nxge_intr_type.intr_registered = B_TRUE;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "\nAdded advanced nxge add_intr_adv "
+ "intr type 0x%x\n", type));
+
+ return (status);
+ }
+ }
+
+ if (!nxgep->nxge_intr_type.intr_registered) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_add_intrs: "
+ "failed to register interrupts"));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_add_intrs"));
+ return (status);
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_add_soft_intrs(p_nxge_t nxgep)
+{
+
+ int ddi_status = DDI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_soft_intrs"));
+
+ nxgep->resched_id = NULL;
+ nxgep->resched_running = B_FALSE;
+ ddi_status = ddi_add_softintr(nxgep->dip, DDI_SOFTINT_LOW,
+ &nxgep->resched_id,
+ NULL, NULL, nxge_reschedule, (caddr_t)nxgep);
+ if (ddi_status != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_add_soft_intrs: "
+ "ddi_add_softintrs failed: status 0x%08x",
+ ddi_status));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_ddi_add_soft_intrs"));
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_add_intrs_adv(p_nxge_t nxgep)
+{
+ int intr_type;
+ p_nxge_intr_t intrp;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv"));
+
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+ intr_type = intrp->intr_type;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_add_intrs_adv: type 0x%x",
+ intr_type));
+
+ switch (intr_type) {
+ case DDI_INTR_TYPE_MSI: /* 0x2 */
+ case DDI_INTR_TYPE_MSIX: /* 0x4 */
+ return (nxge_add_intrs_adv_type(nxgep, intr_type));
+
+ case DDI_INTR_TYPE_FIXED: /* 0x1 */
+ return (nxge_add_intrs_adv_type_fix(nxgep, intr_type));
+
+ default:
+ return (NXGE_ERROR);
+ }
+}
+
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_add_intrs_adv_type(p_nxge_t nxgep, uint32_t int_type)
+{
+ dev_info_t *dip = nxgep->dip;
+ p_nxge_ldg_t ldgp;
+ p_nxge_intr_t intrp;
+ uint_t *inthandler;
+ void *arg1, *arg2;
+ int behavior;
+ int nintrs, navail;
+ int nactual, nrequired;
+ int inum = 0;
+ int x, y;
+ int ddi_status = DDI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type"));
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+ intrp->start_inum = 0;
+
+ ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
+ if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_intr_get_nintrs() failed, status: 0x%x%, "
+ "nintrs: %d", ddi_status, nintrs));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
+ if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_intr_get_navail() failed, status: 0x%x%, "
+ "nintrs: %d", ddi_status, navail));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "ddi_intr_get_navail() returned: nintrs %d, navail %d",
+ nintrs, navail));
+
+ if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) {
+ /* MSI must be power of 2 */
+ if ((navail & 16) == 16) {
+ navail = 16;
+ } else if ((navail & 8) == 8) {
+ navail = 8;
+ } else if ((navail & 4) == 4) {
+ navail = 4;
+ } else if ((navail & 2) == 2) {
+ navail = 2;
+ } else {
+ navail = 1;
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "ddi_intr_get_navail(): (msi power of 2) nintrs %d, "
+ "navail %d", nintrs, navail));
+ }
+
+ behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
+ DDI_INTR_ALLOC_NORMAL);
+ intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
+ intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
+ ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
+ navail, &nactual, behavior);
+ if (ddi_status != DDI_SUCCESS || nactual == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " ddi_intr_alloc() failed: %d",
+ ddi_status));
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
+ (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " ddi_intr_get_pri() failed: %d",
+ ddi_status));
+ /* Free already allocated interrupts */
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ nrequired = 0;
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ default:
+ status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
+ break;
+
+ case N2_NIU:
+ status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
+ break;
+ }
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_add_intrs_adv_typ:nxge_ldgv_init "
+ "failed: 0x%x", status));
+ /* Free already allocated interrupts */
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (status);
+ }
+
+ ldgp = nxgep->ldgvp->ldgp;
+ for (x = 0; x < nrequired; x++, ldgp++) {
+ ldgp->vector = (uint8_t)x;
+ ldgp->intdata = SID_DATA(ldgp->func, x);
+ arg1 = ldgp->ldvp;
+ arg2 = nxgep;
+ if (ldgp->nldvs == 1) {
+ inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "nxge_add_intrs_adv_type: "
+ "arg1 0x%x arg2 0x%x: "
+ "1-1 int handler (entry %d intdata 0x%x)\n",
+ arg1, arg2,
+ x, ldgp->intdata));
+ } else if (ldgp->nldvs > 1) {
+ inthandler = (uint_t *)ldgp->sys_intr_handler;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "nxge_add_intrs_adv_type: "
+ "arg1 0x%x arg2 0x%x: "
+ "nldevs %d int handler "
+ "(entry %d intdata 0x%x)\n",
+ arg1, arg2,
+ ldgp->nldvs, x, ldgp->intdata));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_add_intrs_adv_type: ddi_add_intr(inum) #%d "
+ "htable 0x%llx", x, intrp->htable[x]));
+
+ if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
+ (ddi_intr_handler_t *)inthandler, arg1, arg2))
+ != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_add_intrs_adv_type: failed #%d "
+ "status 0x%x", x, ddi_status));
+ for (y = 0; y < intrp->intr_added; y++) {
+ (void) ddi_intr_remove_handler(
+ intrp->htable[y]);
+ }
+ /* Free already allocated intr */
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+ kmem_free(intrp->htable, intrp->intr_size);
+
+ (void) nxge_ldgv_uninit(nxgep);
+
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+ intrp->intr_added++;
+ }
+
+ intrp->msi_intx_cnt = nactual;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d",
+ navail, nactual,
+ intrp->msi_intx_cnt,
+ intrp->intr_added));
+
+ (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
+
+ (void) nxge_intr_ldgv_init(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type"));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_add_intrs_adv_type_fix(p_nxge_t nxgep, uint32_t int_type)
+{
+ dev_info_t *dip = nxgep->dip;
+ p_nxge_ldg_t ldgp;
+ p_nxge_intr_t intrp;
+ uint_t *inthandler;
+ void *arg1, *arg2;
+ int behavior;
+ int nintrs, navail;
+ int nactual, nrequired;
+ int inum = 0;
+ int x, y;
+ int ddi_status = DDI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_add_intrs_adv_type_fix"));
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+ intrp->start_inum = 0;
+
+ ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs);
+ if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "ddi_intr_get_nintrs() failed, status: 0x%x%, "
+ "nintrs: %d", status, nintrs));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ ddi_status = ddi_intr_get_navail(dip, int_type, &navail);
+ if ((ddi_status != DDI_SUCCESS) || (navail == 0)) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "ddi_intr_get_navail() failed, status: 0x%x%, "
+ "nintrs: %d", ddi_status, navail));
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "ddi_intr_get_navail() returned: nintrs %d, naavail %d",
+ nintrs, navail));
+
+ behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT :
+ DDI_INTR_ALLOC_NORMAL);
+ intrp->intr_size = navail * sizeof (ddi_intr_handle_t);
+ intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP);
+ ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum,
+ navail, &nactual, behavior);
+ if (ddi_status != DDI_SUCCESS || nactual == 0) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " ddi_intr_alloc() failed: %d",
+ ddi_status));
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ if ((ddi_status = ddi_intr_get_pri(intrp->htable[0],
+ (uint_t *)&intrp->pri)) != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " ddi_intr_get_pri() failed: %d",
+ ddi_status));
+ /* Free already allocated interrupts */
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ nrequired = 0;
+ switch (nxgep->niu_type) {
+ case NEPTUNE:
+ case NEPTUNE_2:
+ default:
+ status = nxge_ldgv_init(nxgep, &nactual, &nrequired);
+ break;
+
+ case N2_NIU:
+ status = nxge_ldgv_init_n2(nxgep, &nactual, &nrequired);
+ break;
+ }
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_add_intrs_adv_type_fix:nxge_ldgv_init "
+ "failed: 0x%x", status));
+ /* Free already allocated interrupts */
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+
+ kmem_free(intrp->htable, intrp->intr_size);
+ return (status);
+ }
+
+ ldgp = nxgep->ldgvp->ldgp;
+ for (x = 0; x < nrequired; x++, ldgp++) {
+ ldgp->vector = (uint8_t)x;
+ if (nxgep->niu_type != N2_NIU) {
+ ldgp->intdata = SID_DATA(ldgp->func, x);
+ }
+
+ arg1 = ldgp->ldvp;
+ arg2 = nxgep;
+ if (ldgp->nldvs == 1) {
+ inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "nxge_add_intrs_adv_type_fix: "
+ "1-1 int handler(%d) ldg %d ldv %d "
+ "arg1 $%p arg2 $%p\n",
+ x, ldgp->ldg, ldgp->ldvp->ldv,
+ arg1, arg2));
+ } else if (ldgp->nldvs > 1) {
+ inthandler = (uint_t *)ldgp->sys_intr_handler;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "nxge_add_intrs_adv_type_fix: "
+ "shared ldv %d int handler(%d) ldv %d ldg %d"
+ "arg1 0x%016llx arg2 0x%016llx\n",
+ x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv,
+ arg1, arg2));
+ }
+
+ if ((ddi_status = ddi_intr_add_handler(intrp->htable[x],
+ (ddi_intr_handler_t *)inthandler, arg1, arg2))
+ != DDI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_add_intrs_adv_type_fix: failed #%d "
+ "status 0x%x", x, ddi_status));
+ for (y = 0; y < intrp->intr_added; y++) {
+ (void) ddi_intr_remove_handler(
+ intrp->htable[y]);
+ }
+ for (y = 0; y < nactual; y++) {
+ (void) ddi_intr_free(intrp->htable[y]);
+ }
+ /* Free already allocated intr */
+ kmem_free(intrp->htable, intrp->intr_size);
+
+ (void) nxge_ldgv_uninit(nxgep);
+
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+ intrp->intr_added++;
+ }
+
+ intrp->msi_intx_cnt = nactual;
+
+ (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap);
+
+ status = nxge_intr_ldgv_init(nxgep);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_add_intrs_adv_type_fix"));
+
+ return (status);
+}
+
+static void
+nxge_remove_intrs(p_nxge_t nxgep)
+{
+ int i, inum;
+ p_nxge_intr_t intrp;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs"));
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+ if (!intrp->intr_registered) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_remove_intrs: interrupts not registered"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_intrs:advanced"));
+
+ if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
+ (void) ddi_intr_block_disable(intrp->htable,
+ intrp->intr_added);
+ } else {
+ for (i = 0; i < intrp->intr_added; i++) {
+ (void) ddi_intr_disable(intrp->htable[i]);
+ }
+ }
+
+ for (inum = 0; inum < intrp->intr_added; inum++) {
+ if (intrp->htable[inum]) {
+ (void) ddi_intr_remove_handler(intrp->htable[inum]);
+ }
+ }
+
+ for (inum = 0; inum < intrp->msi_intx_cnt; inum++) {
+ if (intrp->htable[inum]) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "nxge_remove_intrs: ddi_intr_free inum %d "
+ "msi_intx_cnt %d intr_added %d",
+ inum,
+ intrp->msi_intx_cnt,
+ intrp->intr_added));
+
+ (void) ddi_intr_free(intrp->htable[inum]);
+ }
+ }
+
+ kmem_free(intrp->htable, intrp->intr_size);
+ intrp->intr_registered = B_FALSE;
+ intrp->intr_enabled = B_FALSE;
+ intrp->msi_intx_cnt = 0;
+ intrp->intr_added = 0;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_intrs"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_remove_soft_intrs(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_remove_soft_intrs"));
+ if (nxgep->resched_id) {
+ ddi_remove_softintr(nxgep->resched_id);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_remove_soft_intrs: removed"));
+ nxgep->resched_id = NULL;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_remove_soft_intrs"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_intrs_enable(p_nxge_t nxgep)
+{
+ p_nxge_intr_t intrp;
+ int i;
+ int status;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable"));
+
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+
+ if (!intrp->intr_registered) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_intrs_enable: "
+ "interrupts are not registered"));
+ return;
+ }
+
+ if (intrp->intr_enabled) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_intrs_enable: already enabled"));
+ return;
+ }
+
+ if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
+ status = ddi_intr_block_enable(intrp->htable,
+ intrp->intr_added);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
+ "block enable - status 0x%x total inums #%d\n",
+ status, intrp->intr_added));
+ } else {
+ for (i = 0; i < intrp->intr_added; i++) {
+ status = ddi_intr_enable(intrp->htable[i]);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_enable "
+ "ddi_intr_enable:enable - status 0x%x "
+ "total inums %d enable inum #%d\n",
+ status, intrp->intr_added, i));
+ if (status == DDI_SUCCESS) {
+ intrp->intr_enabled = B_TRUE;
+ }
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_enable"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_intrs_disable(p_nxge_t nxgep)
+{
+ p_nxge_intr_t intrp;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intrs_disable"));
+
+ intrp = (p_nxge_intr_t)&nxgep->nxge_intr_type;
+
+ if (!intrp->intr_registered) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable: "
+ "interrupts are not registered"));
+ return;
+ }
+
+ if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) {
+ (void) ddi_intr_block_disable(intrp->htable,
+ intrp->intr_added);
+ } else {
+ for (i = 0; i < intrp->intr_added; i++) {
+ (void) ddi_intr_disable(intrp->htable[i]);
+ }
+ }
+
+ intrp->intr_enabled = B_FALSE;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intrs_disable"));
+}
+
+static nxge_status_t
+nxge_mac_register(p_nxge_t nxgep)
+{
+ mac_register_t *macp;
+ int status;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_mac_register"));
+
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ return (NXGE_ERROR);
+
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = nxgep;
+ macp->m_dip = nxgep->dip;
+ macp->m_src_addr = nxgep->ouraddr.ether_addr_octet;
+ macp->m_callbacks = &nxge_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = nxgep->mac.maxframesize -
+ sizeof (struct ether_header) - ETHERFCSL - 4;
+
+ status = mac_register(macp, &nxgep->mach);
+ mac_free(macp);
+
+ if (status != 0) {
+ cmn_err(CE_WARN,
+ "!nxge_mac_register failed (status %d instance %d)",
+ status, nxgep->instance);
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_mac_register success "
+ "(instance %d)", nxgep->instance));
+
+ return (NXGE_OK);
+}
+
+void
+nxge_err_inject(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
+{
+ ssize_t size;
+ mblk_t *nmp;
+ uint8_t blk_id;
+ uint8_t chan;
+ uint32_t err_id;
+ err_inject_t *eip;
+
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_err_inject"));
+
+ size = 1024;
+ nmp = mp->b_cont;
+ eip = (err_inject_t *)nmp->b_rptr;
+ blk_id = eip->blk_id;
+ err_id = eip->err_id;
+ chan = eip->chan;
+ cmn_err(CE_NOTE, "!blk_id = 0x%x\n", blk_id);
+ cmn_err(CE_NOTE, "!err_id = 0x%x\n", err_id);
+ cmn_err(CE_NOTE, "!chan = 0x%x\n", chan);
+ switch (blk_id) {
+ case MAC_BLK_ID:
+ break;
+ case TXMAC_BLK_ID:
+ break;
+ case RXMAC_BLK_ID:
+ break;
+ case MIF_BLK_ID:
+ break;
+ case IPP_BLK_ID:
+ nxge_ipp_inject_err(nxgep, err_id);
+ break;
+ case TXC_BLK_ID:
+ nxge_txc_inject_err(nxgep, err_id);
+ break;
+ case TXDMA_BLK_ID:
+ nxge_txdma_inject_err(nxgep, err_id, chan);
+ break;
+ case RXDMA_BLK_ID:
+ nxge_rxdma_inject_err(nxgep, err_id, chan);
+ break;
+ case ZCP_BLK_ID:
+ nxge_zcp_inject_err(nxgep, err_id);
+ break;
+ case ESPC_BLK_ID:
+ break;
+ case FFLP_BLK_ID:
+ break;
+ case PHY_BLK_ID:
+ break;
+ case ETHER_SERDES_BLK_ID:
+ break;
+ case PCIE_SERDES_BLK_ID:
+ break;
+ case VIR_BLK_ID:
+ break;
+ }
+
+ nmp->b_wptr = nmp->b_rptr + size;
+ NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_err_inject"));
+
+ miocack(wq, mp, (int)size, 0);
+}
+
+static int
+nxge_init_common_dev(p_nxge_t nxgep)
+{
+ p_nxge_hw_list_t hw_p;
+ dev_info_t *p_dip;
+
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device"));
+
+ p_dip = nxgep->p_dip;
+ MUTEX_ENTER(&nxge_common_lock);
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_init_common_dev:func # %d",
+ nxgep->function_num));
+ /*
+ * Loop through existing per neptune hardware list.
+ */
+ for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_init_common_device:func # %d "
+ "hw_p $%p parent dip $%p",
+ nxgep->function_num,
+ hw_p,
+ p_dip));
+ if (hw_p->parent_devp == p_dip) {
+ nxgep->nxge_hw_p = hw_p;
+ hw_p->ndevs++;
+ hw_p->nxge_p[nxgep->function_num] = nxgep;
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_init_common_device:func # %d "
+ "hw_p $%p parent dip $%p "
+ "ndevs %d (found)",
+ nxgep->function_num,
+ hw_p,
+ p_dip,
+ hw_p->ndevs));
+ break;
+ }
+ }
+
+ if (hw_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_init_common_device:func # %d "
+ "parent dip $%p (new)",
+ nxgep->function_num,
+ p_dip));
+ hw_p = kmem_zalloc(sizeof (nxge_hw_list_t), KM_SLEEP);
+ hw_p->parent_devp = p_dip;
+ hw_p->magic = NXGE_NEPTUNE_MAGIC;
+ nxgep->nxge_hw_p = hw_p;
+ hw_p->ndevs++;
+ hw_p->nxge_p[nxgep->function_num] = nxgep;
+ hw_p->next = nxge_hw_list;
+
+ MUTEX_INIT(&hw_p->nxge_cfg_lock, NULL, MUTEX_DRIVER, NULL);
+ MUTEX_INIT(&hw_p->nxge_tcam_lock, NULL, MUTEX_DRIVER, NULL);
+ MUTEX_INIT(&hw_p->nxge_vlan_lock, NULL, MUTEX_DRIVER, NULL);
+ MUTEX_INIT(&hw_p->nxge_mdio_lock, NULL, MUTEX_DRIVER, NULL);
+ MUTEX_INIT(&hw_p->nxge_mii_lock, NULL, MUTEX_DRIVER, NULL);
+
+ nxge_hw_list = hw_p;
+ }
+
+ MUTEX_EXIT(&nxge_common_lock);
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_init_common_device (nxge_hw_list) $%p",
+ nxge_hw_list));
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<== nxge_init_common_device"));
+
+ return (NXGE_OK);
+}
+
+static void
+nxge_uninit_common_dev(p_nxge_t nxgep)
+{
+ p_nxge_hw_list_t hw_p, h_hw_p;
+ dev_info_t *p_dip;
+
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device"));
+ if (nxgep->nxge_hw_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "<== nxge_uninit_common_device (no common)"));
+ return;
+ }
+
+ MUTEX_ENTER(&nxge_common_lock);
+ h_hw_p = nxge_hw_list;
+ for (hw_p = nxge_hw_list; hw_p; hw_p = hw_p->next) {
+ p_dip = hw_p->parent_devp;
+ if (nxgep->nxge_hw_p == hw_p &&
+ p_dip == nxgep->p_dip &&
+ nxgep->nxge_hw_p->magic == NXGE_NEPTUNE_MAGIC &&
+ hw_p->magic == NXGE_NEPTUNE_MAGIC) {
+
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_uninit_common_device:func # %d "
+ "hw_p $%p parent dip $%p "
+ "ndevs %d (found)",
+ nxgep->function_num,
+ hw_p,
+ p_dip,
+ hw_p->ndevs));
+
+ nxgep->nxge_hw_p = NULL;
+ if (hw_p->ndevs) {
+ hw_p->ndevs--;
+ }
+ hw_p->nxge_p[nxgep->function_num] = NULL;
+ if (!hw_p->ndevs) {
+ MUTEX_DESTROY(&hw_p->nxge_vlan_lock);
+ MUTEX_DESTROY(&hw_p->nxge_tcam_lock);
+ MUTEX_DESTROY(&hw_p->nxge_cfg_lock);
+ MUTEX_DESTROY(&hw_p->nxge_mdio_lock);
+ MUTEX_DESTROY(&hw_p->nxge_mii_lock);
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_uninit_common_device: "
+ "func # %d "
+ "hw_p $%p parent dip $%p "
+ "ndevs %d (last)",
+ nxgep->function_num,
+ hw_p,
+ p_dip,
+ hw_p->ndevs));
+
+ if (hw_p == nxge_hw_list) {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_uninit_common_device:"
+ "remove head func # %d "
+ "hw_p $%p parent dip $%p "
+ "ndevs %d (head)",
+ nxgep->function_num,
+ hw_p,
+ p_dip,
+ hw_p->ndevs));
+ nxge_hw_list = hw_p->next;
+ } else {
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_uninit_common_device:"
+ "remove middle func # %d "
+ "hw_p $%p parent dip $%p "
+ "ndevs %d (middle)",
+ nxgep->function_num,
+ hw_p,
+ p_dip,
+ hw_p->ndevs));
+ h_hw_p->next = hw_p->next;
+ }
+
+ KMEM_FREE(hw_p, sizeof (nxge_hw_list_t));
+ }
+ break;
+ } else {
+ h_hw_p = hw_p;
+ }
+ }
+
+ MUTEX_EXIT(&nxge_common_lock);
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL,
+ "==> nxge_uninit_common_device (nxge_hw_list) $%p",
+ nxge_hw_list));
+
+ NXGE_DEBUG_MSG((nxgep, MOD_CTL, "<= nxge_uninit_common_device"));
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_ndd.c b/usr/src/uts/sun4v/io/nxge/nxge_ndd.c
new file mode 100644
index 0000000000..c14ee854e0
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_ndd.c
@@ -0,0 +1,2840 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <inet/common.h>
+#include <inet/mi.h>
+#include <inet/nd.h>
+
+extern uint64_t npi_debug_level;
+
+#define NXGE_PARAM_MAC_RW NXGE_PARAM_RW | NXGE_PARAM_MAC | \
+ NXGE_PARAM_NDD_WR_OK | NXGE_PARAM_READ_PROP
+
+#define NXGE_PARAM_MAC_DONT_SHOW NXGE_PARAM_RW | NXGE_PARAM_MAC | \
+ NXGE_PARAM_DONT_SHOW
+
+
+#define NXGE_PARAM_RXDMA_RW NXGE_PARAM_RWP | NXGE_PARAM_RXDMA | \
+ NXGE_PARAM_NDD_WR_OK | NXGE_PARAM_READ_PROP
+
+#define NXGE_PARAM_RXDMA_RWC NXGE_PARAM_RWP | NXGE_PARAM_RXDMA | \
+ NXGE_PARAM_INIT_ONLY | NXGE_PARAM_READ_PROP
+
+
+#define NXGE_PARAM_L2CLASS_CFG NXGE_PARAM_RW | NXGE_PARAM_PROP_ARR32 | \
+ NXGE_PARAM_READ_PROP | NXGE_PARAM_NDD_WR_OK
+
+
+#define NXGE_PARAM_CLASS_RWS NXGE_PARAM_RWS | \
+ NXGE_PARAM_READ_PROP
+
+#define NXGE_PARAM_ARRAY_INIT_SIZE 0x20ULL
+
+#define SET_RX_INTR_TIME_DISABLE 0
+#define SET_RX_INTR_TIME_ENABLE 1
+#define SET_RX_INTR_PKTS 2
+
+#define BASE_ANY 0
+#define BASE_BINARY 2
+#define BASE_HEX 16
+#define BASE_DECIMAL 10
+#define ALL_FF_64 0xFFFFFFFFFFFFFFFFULL
+#define ALL_FF_32 0xFFFFFFFFUL
+
+#define NXGE_NDD_INFODUMP_BUFF_SIZE 2048 /* is 2k enough? */
+
+#define NXGE_NDD_INFODUMP_BUFF_8K 8192
+#define NXGE_NDD_INFODUMP_BUFF_16K 0x2000
+#define NXGE_NDD_INFODUMP_BUFF_64K 0x8000
+
+#define PARAM_OUTOF_RANGE(vptr, eptr, rval, pa) \
+ ((vptr == eptr) || (rval < pa->minimum) || (rval > pa->maximum))
+
+#define ADVANCE_PRINT_BUFFER(pmp, plen, rlen) { \
+ ((mblk_t *)pmp)->b_wptr += plen; \
+ rlen -= plen; \
+ }
+
+static void nxge_set_dev_params(p_nxge_t);
+static int nxge_param_rx_intr_pkts(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+static int nxge_param_rx_intr_time(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+static int nxge_param_set_mac(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+static int nxge_param_set_port_rdc(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+
+static int nxge_param_set_grp_rdc(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+
+static int nxge_param_set_ether_usr(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_set_ip_usr(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_set_ip_opt(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_set_vlan_rdcgrp(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_set_mac_rdcgrp(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_fflp_hash_init(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+
+static int nxge_param_llc_snap_enable(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+
+static int nxge_param_hash_lookup_enable(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+
+static int nxge_param_tcam_enable(p_nxge_t, queue_t *,
+ mblk_t *, char *, caddr_t);
+
+static int nxge_param_get_rxdma_info(p_nxge_t, queue_t *q,
+ p_mblk_t, caddr_t);
+static int nxge_param_get_txdma_info(p_nxge_t, queue_t *q,
+ p_mblk_t, caddr_t);
+
+static int nxge_param_get_vlan_rdcgrp(p_nxge_t, queue_t *,
+ p_mblk_t, caddr_t);
+static int nxge_param_get_mac_rdcgrp(p_nxge_t, queue_t *,
+ p_mblk_t, caddr_t);
+static int nxge_param_get_rxdma_rdcgrp_info(p_nxge_t, queue_t *,
+ p_mblk_t, caddr_t);
+
+static int nxge_param_get_ip_opt(p_nxge_t, queue_t *, mblk_t *, caddr_t);
+
+static int
+nxge_param_get_mac(p_nxge_t, queue_t *q, p_mblk_t, caddr_t);
+
+static int nxge_param_get_debug_flag(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_set_nxge_debug_flag(p_nxge_t, queue_t *, mblk_t *,
+ char *, caddr_t);
+static int nxge_param_set_npi_debug_flag(p_nxge_t,
+ queue_t *, mblk_t *,
+ char *, caddr_t);
+
+
+static int nxge_param_dump_rdc(p_nxge_t, queue_t *q, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_tdc(p_nxge_t, queue_t *q, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_mac_regs(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_ipp_regs(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_fflp_regs(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_vlan_table(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_rdc_table(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+static int nxge_param_dump_ptrs(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+
+
+static boolean_t nxge_param_link_update(p_nxge_t);
+
+/*
+ * Global array of Neptune changable parameters.
+ * This array is initialized to correspond to the default
+ * Neptune 4 port configuration. This array would be copied
+ * into each port's parameter structure and modifed per
+ * fcode and nxge.conf configuration. Later, the parameters are
+ * exported to ndd to display and run-time configuration (at least
+ * some of them).
+ *
+ */
+
+static nxge_param_t nxge_param_arr[] = {
+/* min max value old hw-name conf-name */
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 999, 1000, 0,
+ "instance", "instance"},
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 999, 1000, 0,
+ "main-instance", "main_instance"},
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 3, 0, 0,
+ "function-number", "function_number"},
+/* Partition Id */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 8, 0, 0,
+ "partition-id", "partition_id"},
+/* Read Write Permission Mode */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_DONT_SHOW,
+ 0, 2, 0, 0,
+ "read-write-mode", "read_write_mode"},
+/* hw cfg types */
+/* control the DMA config of Neptune/NIU */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ CFG_DEFAULT, CFG_CUSTOM, CFG_DEFAULT, CFG_DEFAULT,
+ "niu-cfg-type", "niu_cfg_type"},
+/* control the TXDMA config of the Port controlled by tx-quick-cfg */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ CFG_DEFAULT, CFG_CUSTOM, CFG_NOT_SPECIFIED, CFG_DEFAULT,
+ "tx-qcfg-type", "tx_qcfg_type"},
+/* control the RXDMA config of the Port controlled by rx-quick-cfg */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ CFG_DEFAULT, CFG_CUSTOM, CFG_NOT_SPECIFIED, CFG_DEFAULT,
+ "rx-qcfg-type", "rx_qcfg_type"},
+
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_RW | NXGE_PARAM_DONT_SHOW,
+ 0, 1, 0, 0,
+ "master-cfg-enable", "master_cfg_enable"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_RW | NXGE_PARAM_DONT_SHOW,
+ 0, 1, 0, 0,
+ "master-cfg-value", "master_cfg_value"},
+
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "adv-autoneg-cap", "adv_autoneg_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "adv-10gfdx-cap", "adv_10gfdx_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_DONT_SHOW,
+ 0, 1, 0, 0,
+ "adv-10ghdx-cap", "adv_10ghdx_cap"},
+
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "adv-1000fdx-cap", "adv_1000fdx_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_DONT_SHOW,
+ 0, 1, 0, 0,
+ "adv-1000hdx-cap", "adv_1000hdx_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_DONT_SHOW,
+ 0, 1, 0, 0,
+ "adv-100T4-cap", "adv_100T4_cap" },
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "adv-100fdx-cap", "adv_100fdx_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_DONT_SHOW,
+ 0, 1, 0, 0,
+ "adv-100hdx-cap", "adv_100hdx_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "adv-10fdx-cap", "adv_10fdx_cap" },
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_DONT_SHOW,
+ 0, 1, 0, 0,
+ "adv-10hdx-cap", "adv_10hdx_cap" },
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 0, 0,
+ "adv-asmpause-cap", "adv_asmpause_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 0, 0,
+ "adv-pause-cap", "adv_pause_cap"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 0, 0,
+ "use-int-xcvr", "use_int_xcvr"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 1, 1,
+ "enable-ipg0", "enable_ipg0"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 255, 8, 8,
+ "ipg0", "ipg0"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 255, 8, 8,
+ "ipg1", "ipg1"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 255, 4, 4,
+ "ipg2", "ipg2"},
+{ nxge_param_get_mac, nxge_param_set_mac,
+ NXGE_PARAM_MAC_RW,
+ 0, 1, 0, 0,
+ "accept-jumbo", "accept_jumbo"},
+
+/* Transmit DMA channels */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 3, 0, 0,
+ "tx-dma-weight", "tx_dma_weight"},
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 31, 0, 0,
+ "tx-dma-channels-begin", "tx_dma_channels_begin"},
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 32, 0, 0,
+ "tx-dma-channels", "tx_dma_channels"},
+{ nxge_param_get_txdma_info, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 32, 0, 0,
+ "tx-dma-info", "tx_dma_info"},
+/* Receive DMA channels */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 31, 0, 0,
+ "rx-dma-channels-begin", "rx_dma_channels_begin"},
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 32, 0, 0,
+ "rx-dma-channels", "rx_dma_channels"},
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 65535, PT_DRR_WT_DEFAULT_10G, 0,
+ "rx-drr-weight", "rx_drr_weight" },
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_READ_PROP,
+ 0, 1, 1, 0,
+ "rx-full-header", "rx_full_header"},
+{ nxge_param_get_rxdma_info, NULL,
+ NXGE_PARAM_READ,
+ 0, 32, 0, 0,
+ "rx-dma-info", "rx_dma_info"},
+
+{ nxge_param_get_rxdma_info, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_DONT_SHOW,
+ NXGE_RBR_RBB_MIN, NXGE_RBR_RBB_MAX, NXGE_RBR_RBB_DEFAULT, 0,
+ "rx-rbr-size", "rx_rbr_size"},
+
+{ nxge_param_get_rxdma_info, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_DONT_SHOW,
+ NXGE_RCR_MIN, NXGE_RCR_MAX, NXGE_RCR_DEFAULT, 0,
+ "rx-rcr-size", "rx_rcr_size"},
+
+{ nxge_param_get_generic, nxge_param_set_port_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 0, 0,
+ "default-port-rdc", "default_port_rdc"},
+
+{ nxge_param_get_generic, nxge_param_rx_intr_time,
+ NXGE_PARAM_RXDMA_RW | NXGE_PARAM_PROP_ARR32,
+ 0, 31, 0, 0,
+ "rxdma-intr-time", "rxdma_intr_time"},
+{ nxge_param_get_generic, nxge_param_rx_intr_pkts,
+ NXGE_PARAM_RXDMA_RW | NXGE_PARAM_PROP_ARR32,
+ 0, 31, 0, 0,
+ "rxdma-intr-pkts", "rxdma_intr_pkts"},
+
+{ nxge_param_get_generic, NULL, NXGE_PARAM_READ_PROP,
+ 0, 8, 0, 0,
+ "rx-rdc-grps-begin", "rx_rdc_grps_begin"},
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ_PROP,
+ 0, 8, 0, 0,
+ "rx-rdc-grps", "rx_rdc_grps"},
+
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 0, 0,
+ "default-grp0-rdc", "default_grp0_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 2, 0,
+ "default-grp1-rdc", "default_grp1_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 4, 0,
+ "default-grp2-rdc", "default_grp2_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 6, 0,
+ "default-grp3-rdc", "default_grp3_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 8, 0,
+ "default-grp4-rdc", "default_grp4_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 10, 0,
+ "default-grp5-rdc", "default_grp5_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 12, 0, "default-grp6-rdc", "default_grp6_rdc"},
+{ nxge_param_get_generic, nxge_param_set_grp_rdc,
+ NXGE_PARAM_RXDMA_RW,
+ 0, 15, 14, 0,
+ "default-grp7-rdc", "default_grp7_rdc"},
+
+{ nxge_param_get_rxdma_rdcgrp_info, NULL,
+ NXGE_PARAM_READ | NXGE_PARAM_CMPLX,
+ 0, 8, 0, 0,
+ "rdc-groups-info", "rdc_groups_info"},
+/* Logical device groups */
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 63, 0, 0,
+ "start-ldg", "start_ldg" },
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ,
+ 0, 64, 0, 0,
+ "max-ldg", "max_ldg" },
+
+/* MAC table information */
+{ nxge_param_get_mac_rdcgrp, nxge_param_set_mac_rdcgrp,
+ NXGE_PARAM_L2CLASS_CFG,
+ 0, 31, 0, 0,
+ "mac-2rdc-grp", "mac_2rdc_grp"},
+/* VLAN table information */
+
+{ nxge_param_get_vlan_rdcgrp, nxge_param_set_vlan_rdcgrp,
+ NXGE_PARAM_L2CLASS_CFG,
+ 0, 31, 0, 0,
+ "vlan-2rdc-grp", "vlan_2rdc_grp"},
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_READ_PROP | NXGE_PARAM_READ | NXGE_PARAM_PROP_ARR32,
+ 0, 0x0ffff, 0x0ffff, 0,
+ "fcram-part-cfg", "fcram_part_cfg"},
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x10, 0xa, 0,
+ "fcram-access-ratio", "fcram_access_ratio"},
+
+{ nxge_param_get_generic, NULL,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x10, 0xa, 0,
+ "tcam-access-ratio", "tcam_access_ratio"},
+
+
+{ nxge_param_get_generic, nxge_param_tcam_enable,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x1, 0x0, 0,
+ "tcam-enable", "tcam_enable"},
+
+{ nxge_param_get_generic, nxge_param_hash_lookup_enable,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x01, 0x0, 0,
+ "hash-lookup-enable", "hash_lookup_enable"},
+
+{ nxge_param_get_generic, nxge_param_llc_snap_enable,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x01, 0x01, 0,
+ "llc-snap-enable", "llc_snap_enable"},
+
+{ nxge_param_get_generic, nxge_param_fflp_hash_init,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, ALL_FF_32, 0,
+ "h1-init-value", "h1_init_value"},
+{ nxge_param_get_generic, nxge_param_fflp_hash_init,
+ NXGE_PARAM_CLASS_RWS,
+ 0, 0x0ffff, 0x0ffff, 0,
+ "h2-init-value", "h2_init_value"},
+
+{ nxge_param_get_generic, nxge_param_set_ether_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ether-usr1", "class_cfg_ether_usr1"},
+
+{ nxge_param_get_generic, nxge_param_set_ether_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ether-usr2", "class_cfg_ether_usr2"},
+{ nxge_param_get_generic, nxge_param_set_ip_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ip-usr4", "class_cfg_ip_usr4"},
+{ nxge_param_get_generic, nxge_param_set_ip_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ip-usr5", "class_cfg_ip_usr5"},
+{ nxge_param_get_generic, nxge_param_set_ip_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ip-usr6", "class_cfg_ip_usr6"},
+{ nxge_param_get_generic, nxge_param_set_ip_usr,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-cfg-ip-usr7", "class_cfg_ip_usr7"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-opt-ip-usr4", "class_opt_ip_usr4"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-opt-ip-usr5", "class_opt_ip_usr5"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-opt-ip-usr6", "class_opt_ip_usr6"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS | NXGE_PARAM_DONT_SHOW,
+ 0, ALL_FF_32, 0x0, 0,
+ "class-opt-ip-usr7", "class_opt_ip_usr7"},
+
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv4-tcp", "class_opt_ipv4_tcp"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv4-udp", "class_opt_ipv4_udp"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv4-ah", "class_opt_ipv4_ah"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv4-sctp", "class_opt_ipv4_sctp"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv6-tcp", "class_opt_ipv6_tcp"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv6-udp", "class_opt_ipv6_udp"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv6-ah", "class_opt_ipv6_ah"},
+{ nxge_param_get_ip_opt, nxge_param_set_ip_opt,
+ NXGE_PARAM_CLASS_RWS,
+ 0, ALL_FF_32, NXGE_CLASS_FLOW_GEN_SERVER, 0,
+ "class-opt-ipv6-sctp", "class_opt_ipv6_sctp"},
+
+{ nxge_param_get_debug_flag, nxge_param_set_nxge_debug_flag,
+ NXGE_PARAM_RW,
+ 0ULL, ALL_FF_64, 0ULL, 0ULL,
+ "nxge-debug-flag", "nxge_debug_flag"},
+{ nxge_param_get_debug_flag, nxge_param_set_npi_debug_flag,
+ NXGE_PARAM_RW,
+ 0ULL, ALL_FF_64, 0ULL, 0ULL,
+ "npi-debug-flag", "npi_debug_flag"},
+
+{ nxge_param_dump_tdc, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-tdc", "dump_tdc"},
+
+{ nxge_param_dump_rdc, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-rdc", "dump_rdc"},
+
+{ nxge_param_dump_mac_regs, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-mac-regs", "dump_mac_regs"},
+
+{ nxge_param_dump_ipp_regs, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-ipp-regs", "dump_ipp_regs"},
+
+{ nxge_param_dump_fflp_regs, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-fflp-regs", "dump_fflp_regs"},
+
+{ nxge_param_dump_vlan_table, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-vlan-table", "dump_vlan_table"},
+
+{ nxge_param_dump_rdc_table, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-rdc-table", "dump_rdc_table"},
+
+{ nxge_param_dump_ptrs, NULL, NXGE_PARAM_READ,
+ 0, 0x0fffffff, 0x0fffffff, 0,
+ "dump-ptrs", "dump_ptrs"},
+
+
+{ NULL, NULL, NXGE_PARAM_READ | NXGE_PARAM_DONT_SHOW,
+ 0, 0x0fffffff, 0x0fffffff, 0, "end", "end" },
+};
+
+extern void *nxge_list;
+
+
+void
+nxge_get_param_soft_properties(p_nxge_t nxgep)
+{
+
+ p_nxge_param_t param_arr;
+ uint_t prop_len;
+ int i, j;
+ uint32_t param_count;
+ uint32_t *int_prop_val;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, " ==> nxge_get_param_soft_properties"));
+
+ param_arr = nxgep->param_arr;
+ param_count = nxgep->param_count;
+ for (i = 0; i < param_count; i++) {
+
+ if ((param_arr[i].type & NXGE_PARAM_READ_PROP) == 0)
+ continue;
+
+ if ((param_arr[i].type & NXGE_PARAM_PROP_STR))
+ continue;
+
+ if ((param_arr[i].type & NXGE_PARAM_PROP_ARR32) ||
+ (param_arr[i].type & NXGE_PARAM_PROP_ARR64)) {
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
+ nxgep->dip, 0,
+ param_arr[i].fcode_name,
+ (int **)&int_prop_val,
+ (uint_t *)&prop_len)
+ == DDI_PROP_SUCCESS) {
+ uint32_t *cfg_value;
+ uint64_t prop_count;
+ if (prop_len > NXGE_PARAM_ARRAY_INIT_SIZE)
+ prop_len = NXGE_PARAM_ARRAY_INIT_SIZE;
+
+ cfg_value = (uint32_t *)param_arr[i].value;
+ for (j = 0; j < prop_len; j++) {
+ cfg_value[j] = int_prop_val[j];
+ }
+ prop_count = prop_len;
+ param_arr[i].type |=
+ (prop_count << NXGE_PARAM_ARRAY_CNT_SHIFT);
+
+ ddi_prop_free(int_prop_val);
+ }
+
+ continue;
+ }
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ param_arr[i].fcode_name,
+ (int **)&int_prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ if ((*int_prop_val >= param_arr[i].minimum) &&
+ (*int_prop_val <= param_arr[i].maximum))
+ param_arr[i].value = *int_prop_val;
+#ifdef NXGE_DEBUG_ERROR
+ else {
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "nxge%d: 'prom' file"
+ " parameter error\n",
+ nxgep->instance));
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "Parameter keyword '%s'"
+ " is outside valid range\n",
+ param_arr[i].name));
+ }
+#endif
+ ddi_prop_free(int_prop_val);
+ }
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ param_arr[i].name,
+ (int **)&int_prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ if ((*int_prop_val >= param_arr[i].minimum) &&
+ (*int_prop_val <= param_arr[i].maximum))
+ param_arr[i].value = *int_prop_val;
+#ifdef NXGE_DEBUG_ERROR
+ else {
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "nxge%d: 'conf' file"
+ " parameter error\n",
+ nxgep->instance));
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "Parameter keyword '%s'"
+ "is outside valid range\n",
+ param_arr[i].name));
+ }
+#endif
+ ddi_prop_free(int_prop_val);
+ }
+ }
+}
+
+
+
+
+static int
+nxge_private_param_register(p_nxge_t nxgep, p_nxge_param_t param_arr)
+{
+
+ int status = B_TRUE;
+ int channel;
+ uint8_t grp;
+ char *prop_name;
+ char *end;
+ uint32_t name_chars;
+
+ NXGE_DEBUG_MSG((nxgep, NDD2_CTL,
+ " nxge_private_param_register %s",
+ param_arr->name));
+
+ if ((param_arr->type & NXGE_PARAM_PRIV) != NXGE_PARAM_PRIV)
+ return (B_TRUE);
+ prop_name = param_arr->name;
+ if (param_arr->type & NXGE_PARAM_RXDMA) {
+ if (strncmp("rxdma_intr", prop_name, 10) == 0)
+ return (B_TRUE);
+ name_chars = strlen("default_grp");
+ if (strncmp("default_grp", prop_name, name_chars) == 0) {
+ prop_name += name_chars;
+ grp = mi_strtol(prop_name, &end, 10);
+ /* now check if this rdcgrp is in config */
+ return (nxge_check_rdcgrp_port_member(nxgep, grp));
+ }
+ name_chars = strlen(prop_name);
+ if (strncmp("default_port_rdc", prop_name, name_chars) == 0) {
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+ }
+
+ if (param_arr->type & NXGE_PARAM_TXDMA) {
+ name_chars = strlen("txdma");
+ if (strncmp("txdma", prop_name, name_chars) == 0) {
+ prop_name += name_chars;
+ channel = mi_strtol(prop_name, &end, 10);
+ /* now check if this rdc is in config */
+ NXGE_DEBUG_MSG((nxgep, NDD2_CTL,
+ " nxge_private_param_register: %d",
+ channel));
+ return (nxge_check_txdma_port_member(nxgep, channel));
+ }
+ return (B_FALSE);
+ }
+
+ status = B_FALSE;
+ NXGE_DEBUG_MSG((nxgep, NDD2_CTL, "<== nxge_private_param_register"));
+
+ return (status);
+}
+
+void
+nxge_setup_param(p_nxge_t nxgep)
+{
+ p_nxge_param_t param_arr;
+ int i;
+ pfi_t set_pfi;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_setup_param"));
+ /*
+ * Make sure the param_instance is set to a valid device instance.
+ */
+ if (nxge_param_arr[param_instance].value == 1000)
+ nxge_param_arr[param_instance].value = nxgep->instance;
+
+ param_arr = nxgep->param_arr;
+ param_arr[param_instance].value = nxgep->instance;
+ param_arr[param_function_number].value = nxgep->function_num;
+
+ for (i = 0; i < nxgep->param_count; i++) {
+ if ((param_arr[i].type & NXGE_PARAM_PRIV) &&
+ (nxge_private_param_register(nxgep,
+ &param_arr[i]) ==
+ B_FALSE)) {
+ param_arr[i].setf = NULL;
+ param_arr[i].getf = NULL;
+ }
+
+ if (param_arr[i].type & NXGE_PARAM_CMPLX)
+ param_arr[i].setf = NULL;
+
+ if (param_arr[i].type & NXGE_PARAM_DONT_SHOW) {
+ param_arr[i].setf = NULL;
+ param_arr[i].getf = NULL;
+ }
+
+ set_pfi = (pfi_t)param_arr[i].setf;
+
+ if ((set_pfi) &&
+ (param_arr[i].type & NXGE_PARAM_INIT_ONLY)) {
+ set_pfi = NULL;
+ }
+
+
+ if (!nxge_nd_load(&nxgep->param_list,
+ param_arr[i].name,
+ (pfi_t)param_arr[i].getf,
+ set_pfi,
+ (caddr_t)&param_arr[i])) {
+ (void) nxge_nd_free(&nxgep->param_list);
+ break;
+ }
+
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_setup_param"));
+}
+
+
+
+void
+nxge_init_param(p_nxge_t nxgep)
+{
+ p_nxge_param_t param_arr;
+ int i, alloc_size;
+ uint64_t alloc_count;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_init_param"));
+ /*
+ * Make sure the param_instance is set to a valid device instance.
+ */
+ if (nxge_param_arr[param_instance].value == 1000)
+ nxge_param_arr[param_instance].value = nxgep->instance;
+
+ param_arr = nxgep->param_arr;
+ if (param_arr == NULL) {
+ param_arr = (p_nxge_param_t)KMEM_ZALLOC(
+ sizeof (nxge_param_arr), KM_SLEEP);
+ }
+ for (i = 0; i < sizeof (nxge_param_arr)/sizeof (nxge_param_t); i++) {
+ param_arr[i] = nxge_param_arr[i];
+ if ((param_arr[i].type & NXGE_PARAM_PROP_ARR32) ||
+ (param_arr[i].type & NXGE_PARAM_PROP_ARR64)) {
+ alloc_count = NXGE_PARAM_ARRAY_INIT_SIZE;
+ alloc_size = alloc_count * sizeof (uint64_t);
+ param_arr[i].value =
+ (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP);
+ param_arr[i].old_value =
+ (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP);
+ param_arr[i].type |=
+ (alloc_count << NXGE_PARAM_ARRAY_ALLOC_SHIFT);
+ }
+ }
+
+ nxgep->param_arr = param_arr;
+ nxgep->param_count = sizeof (nxge_param_arr)/sizeof (nxge_param_t);
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init_param: count %d",
+ nxgep->param_count));
+}
+
+void
+nxge_destroy_param(p_nxge_t nxgep)
+{
+ int i;
+ uint64_t free_size, free_count;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_param"));
+ /*
+ * Make sure the param_instance is set to a valid device instance.
+ */
+ if (nxge_param_arr[param_instance].value == nxgep->instance) {
+ for (i = 0; i <= nxge_param_arr[param_instance].maximum; i++) {
+ if ((ddi_get_soft_state(nxge_list, i) != NULL) &&
+ (i != nxgep->instance))
+ break;
+ }
+ nxge_param_arr[param_instance].value = i;
+ }
+
+ if (nxgep->param_list)
+ nxge_nd_free(&nxgep->param_list);
+ for (i = 0; i < nxgep->param_count; i++)
+ if ((nxgep->param_arr[i].type & NXGE_PARAM_PROP_ARR32) ||
+ (nxgep->param_arr[i].type & NXGE_PARAM_PROP_ARR64)) {
+ free_count = ((nxgep->param_arr[i].type &
+ NXGE_PARAM_ARRAY_ALLOC_MASK) >>
+ NXGE_PARAM_ARRAY_ALLOC_SHIFT);
+ free_count = NXGE_PARAM_ARRAY_INIT_SIZE;
+ free_size = sizeof (uint64_t) * free_count;
+ KMEM_FREE((void *)nxgep->param_arr[i].value, free_size);
+ KMEM_FREE((void *)nxgep->param_arr[i].old_value,
+ free_size);
+ }
+
+ KMEM_FREE(nxgep->param_arr, sizeof (nxge_param_arr));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_param"));
+}
+
+/*
+ * Extracts the value from the 'nxge' parameter array and prints the
+ * parameter value. cp points to the required parameter.
+ */
+/* ARGSUSED */
+int
+
+nxge_param_get_generic(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " ==> nxge_param_get_generic name %s ",
+ pa->name));
+
+ if (pa->value > 0xffffffff)
+ (void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32),
+ (int)(pa->value & 0xffffffff));
+ else
+ (void) mi_mpprintf(mp, "%x", (int)pa->value);
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_generic"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+static int
+nxge_param_get_mac(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_mac"));
+
+ (void) mi_mpprintf(mp, "%d", (uint32_t)pa->value);
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_mac"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+int
+nxge_param_get_txdma_info(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int tdc;
+
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_SIZE;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_txdma_info"));
+
+ (void) mi_mpprintf(mp,
+ "TXDMA Information for Port\t %d \n",
+ nxgep->function_num);
+
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+
+ buf_len = buff_alloc_size;
+
+ mp->b_cont = np;
+
+
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "Total TDCs\t %d\n", nxgep->ntdc);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "TDC\t HW TDC\t\n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ for (tdc = 0; tdc < nxgep->ntdc; tdc++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, "%d\t %d\n",
+ tdc, nxgep->tdc[tdc]);
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_txdma_info"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+int
+nxge_param_get_rxdma_info(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int rdc;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_SIZE;
+
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_rxdma_info"));
+
+ (void) mi_mpprintf(mp,
+ "RXDMA Information for Port\t %d \n",
+ nxgep->function_num);
+
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ /* The following may work even if we cannot get a large buf. */
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+
+ buf_len = buff_alloc_size;
+
+ mp->b_cont = np;
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rbr_rings = rx_rbr_rings->rbr_rings;
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "Total RDCs\t %d\n",
+ p_cfgp->max_rdcs);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "RDC\t HW RDC\t Timeout\t Packets RBR ptr \t"
+ "chunks\t RCR ptr\n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ " %d\t %d\t %x\t\t %x\t $%p\t 0x%x\t $%p\n",
+ rdc, nxgep->rdc[rdc],
+ p_dma_cfgp->rcr_timeout[rdc],
+ p_dma_cfgp->rcr_threshold[rdc],
+ rbr_rings[rdc],
+ rbr_rings[rdc]->num_blocks, rcr_rings[rdc]);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_rxdma_info"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+int
+nxge_param_get_rxdma_rdcgrp_info(p_nxge_t nxgep, queue_t *q,
+ p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int offset, rdc;
+ int i, rdc_grp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_SIZE;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ "==> nxge_param_get_rxdma_rdcgrp_info"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ (void) mi_mpprintf(mp,
+ "RXDMA RDC Group Information for Port\t %d \n",
+ nxgep->function_num);
+
+ rdc_grp = p_cfgp->start_rdc_grpid;
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ /* The following may work even if we cannot get a large buf. */
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+
+ buf_len = buff_alloc_size;
+
+ mp->b_cont = np;
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "Total RDC Groups\t %d \n"
+ "start RDC group\t %d\n",
+ p_cfgp->max_rdc_grpids,
+ p_cfgp->start_rdc_grpid);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+
+ for (i = 0, rdc_grp = p_cfgp->start_rdc_grpid;
+ rdc_grp < (p_cfgp->max_rdc_grpids + p_cfgp->start_rdc_grpid);
+ rdc_grp++, i++) {
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[i];
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "\nRDC Group Info for Group [%d] %d\n"
+ "RDC Count %d\tstart RDC %d\n"
+ "RDC Group Population Information"
+ " (offsets 0 - 15)\n",
+ i, rdc_grp, rdc_grp_p->max_rdcs,
+ rdc_grp_p->start_rdc);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, "\n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+
+ for (rdc = 0; rdc < rdc_grp_p->max_rdcs; rdc++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, "[%d]=%d ", rdc,
+ rdc_grp_p->start_rdc + rdc);
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, "\n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+
+ for (offset = 0; offset < 16; offset++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, " %2d ",
+ rdc_grp_p->rdc[offset]);
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len, "\n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ "<== nxge_param_get_rxdma_rdcgrp_info"));
+ return (0);
+}
+
+
+int
+nxge_mk_mblk_tail_space(p_mblk_t mp, p_mblk_t *nmp, size_t size)
+{
+ p_mblk_t tmp;
+
+ tmp = mp;
+ while (tmp->b_cont)
+ tmp = tmp->b_cont;
+ if ((tmp->b_wptr + size) >= tmp->b_datap->db_lim) {
+ tmp->b_cont = allocb(1024, BPRI_HI);
+ tmp = tmp->b_cont;
+ if (!tmp)
+ return (ENOMEM);
+ }
+ *nmp = tmp;
+ return (0);
+}
+
+/*
+ * Sets the ge parameter to the value in the nxge_param_register using
+ * nxge_nd_load().
+ */
+/* ARGSUSED */
+int
+nxge_param_set_generic(p_nxge_t nxgep, queue_t *q, mblk_t *mp,
+ char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t new_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, " ==> nxge_param_set_generic"));
+ new_value = (uint32_t)mi_strtol(value, &end, 10);
+ if (end == value || new_value < pa->minimum ||
+ new_value > pa->maximum) {
+ return (EINVAL);
+ }
+ pa->value = new_value;
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, " <== nxge_param_set_generic"));
+ return (0);
+}
+
+
+
+/*
+ * Sets the ge parameter to the value in the nxge_param_register using
+ * nxge_nd_load().
+ */
+/* ARGSUSED */
+
+int
+nxge_param_set_instance(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " ==> nxge_param_set_instance"));
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " <== nxge_param_set_instance"));
+ return (0);
+}
+
+/*
+ * Sets the ge parameter to the value in the nxge_param_register using
+ * nxge_nd_load().
+ */
+/* ARGSUSED */
+
+int
+nxge_param_set_mac(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t new_value;
+ int status = 0;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_mac"));
+ new_value = (uint32_t)mi_strtol(value, &end, BASE_DECIMAL);
+ if (PARAM_OUTOF_RANGE(value, end, new_value, pa)) {
+ return (EINVAL);
+ }
+
+ if (pa->value != new_value) {
+ pa->old_value = pa->value;
+ pa->value = new_value;
+ }
+
+ if (!nxge_param_link_update(nxgep)) {
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " false ret from nxge_param_link_update"));
+ status = EINVAL;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_mac"));
+ return (status);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_rx_intr_set(p_nxge_t nxgep, uint16_t value,
+ uint8_t channel, uint8_t type)
+{
+ int status = 0;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_rx_intr_set"));
+
+ /* setup value */
+ switch (type) {
+ case SET_RX_INTR_TIME_DISABLE:
+ status = nxge_rxdma_cfg_rcr_timeout(nxgep, channel,
+ value, 0);
+ break;
+ case SET_RX_INTR_TIME_ENABLE:
+ status = nxge_rxdma_cfg_rcr_timeout(nxgep, channel,
+ value, 1);
+ break;
+ case SET_RX_INTR_PKTS:
+ status = nxge_rxdma_cfg_rcr_threshold(nxgep, channel,
+ value);
+ break;
+ default:
+ status = NXGE_ERROR;
+ break;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_rx_intr_set"));
+ return (status);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_rx_intr_pkts(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ nxge_rcr_param_t *threshold;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint32_t *val_ptr, *old_val_ptr;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_rx_intr_pkts"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ /* now do decoding */
+ /*
+ * format is
+ * bit[30]= enable
+ * bit[29]= remove
+ * bits[23-16] = rdc
+ * bits[15-0] = blanking parameter
+ *
+ */
+ threshold = (nxge_rcr_param_t *)&cfg_value;
+ if ((threshold->rdc < p_cfgp->max_rdcs) &&
+ (threshold->cfg_val < NXGE_RDC_RCR_TIMEOUT_MAX) &&
+ (threshold->cfg_val >= NXGE_RDC_RCR_TIMEOUT_MIN)) {
+ val_ptr = (uint32_t *)pa->value;
+ old_val_ptr = (uint32_t *)pa->old_value;
+ if (val_ptr[threshold->rdc] != cfg_value) {
+ old_val_ptr[threshold->rdc] = val_ptr[threshold->rdc];
+ val_ptr[threshold->rdc] = cfg_value;
+ p_dma_cfgp->rcr_threshold[threshold->rdc] =
+ threshold->cfg_val;
+ cfg_it = B_TRUE;
+ }
+ } else {
+ return (EINVAL);
+ }
+ if (cfg_it == B_TRUE) {
+ status = nxge_param_rx_intr_set(nxgep, threshold->cfg_val,
+ threshold->rdc,
+ SET_RX_INTR_PKTS);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_rx_intr_pkts"));
+ return (0);
+}
+
+
+
+/* ARGSUSED */
+static int
+nxge_param_rx_intr_time(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ nxge_rcr_param_t *tout;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint32_t *val_ptr, *old_val_ptr;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_rx_intr_time"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ /* now do decoding */
+ /*
+ * format is
+ * bit[30]= enable
+ * bit[29]= remove
+ * bits[23-16] = rdc
+ * bits[15-0] = blanking parameter
+ *
+ */
+ tout = (nxge_rcr_param_t *)&cfg_value;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_rx_intr_time value %x",
+ cfg_value));
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_rx_intr_time %x %x",
+ tout->rdc, tout->cfg_val));
+ if ((tout->rdc < p_cfgp->max_rdcs) &&
+ (tout->cfg_val < NXGE_RDC_RCR_TIMEOUT_MAX) &&
+ (tout->cfg_val >= NXGE_RDC_RCR_TIMEOUT_MIN)) {
+ val_ptr = (uint32_t *)pa->value;
+ old_val_ptr = (uint32_t *)pa->old_value;
+ if (val_ptr[tout->rdc] != cfg_value) {
+ old_val_ptr[tout->rdc] = val_ptr[tout->rdc];
+ val_ptr[tout->rdc] = cfg_value;
+ p_dma_cfgp->rcr_timeout[tout->rdc] = tout->cfg_val;
+ cfg_it = B_TRUE;
+ }
+ } else {
+ return (EINVAL);
+ }
+
+ if (cfg_it == B_TRUE) {
+ if (tout->remove)
+ status = nxge_param_rx_intr_set(nxgep,
+ tout->cfg_val, tout->rdc,
+ SET_RX_INTR_TIME_DISABLE);
+ else
+ status = nxge_param_rx_intr_set(nxgep,
+ tout->cfg_val, tout->rdc,
+ SET_RX_INTR_TIME_ENABLE);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_rx_intr_time"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_set_mac_rdcgrp(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint32_t *val_ptr, *old_val_ptr;
+ nxge_param_map_t *mac_map;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ nxge_mv_cfg_t *mac_host_info;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_mac_rdcgrp "));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ mac_host_info = (nxge_mv_cfg_t *)&p_class_cfgp->mac_host_info[0];
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ /* now do decoding */
+ /* */
+ mac_map = (nxge_param_map_t *)&cfg_value;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " cfg_value %x id %x map_to %x",
+ cfg_value, mac_map->param_id,
+ mac_map->map_to));
+
+ if ((mac_map->param_id < p_cfgp->max_macs) &&
+ (mac_map->map_to <
+ (p_cfgp->max_rdc_grpids + p_cfgp->start_rdc_grpid)) &&
+ (mac_map->map_to >= p_cfgp->start_rdc_grpid)) {
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_set_mac_rdcgrp mapping"
+ " id %d grp %d",
+ mac_map->param_id, mac_map->map_to));
+ val_ptr = (uint32_t *)pa->value;
+ old_val_ptr = (uint32_t *)pa->old_value;
+ if (val_ptr[mac_map->param_id] != cfg_value) {
+ old_val_ptr[mac_map->param_id] =
+ val_ptr[mac_map->param_id];
+ val_ptr[mac_map->param_id] = cfg_value;
+ mac_host_info[mac_map->param_id].mpr_npr =
+ mac_map->pref;
+ mac_host_info[mac_map->param_id].flag = 1;
+ mac_host_info[mac_map->param_id].rdctbl =
+ mac_map->map_to;
+ cfg_it = B_TRUE;
+ }
+
+ } else {
+ return (EINVAL);
+ }
+
+ if (cfg_it == B_TRUE) {
+ status = nxge_logical_mac_assign_rdc_table(nxgep,
+ (uint8_t)mac_map->param_id);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_mac_rdcgrp"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_set_vlan_rdcgrp(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint32_t *val_ptr, *old_val_ptr;
+ nxge_param_map_t *vmap, *old_map;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ uint64_t cfgd_vlans;
+ int i, inc = 0, cfg_position;
+ nxge_mv_cfg_t *vlan_tbl;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_vlan_rdcgrp "));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ vlan_tbl = (nxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ /* now do decoding */
+ /* */
+ cfgd_vlans = ((pa->type & NXGE_PARAM_ARRAY_CNT_MASK) >>
+ NXGE_PARAM_ARRAY_CNT_SHIFT);
+
+ if (cfgd_vlans == NXGE_PARAM_ARRAY_INIT_SIZE) {
+ /*
+ * for now, we process only upto max
+ * NXGE_PARAM_ARRAY_INIT_SIZE parameters
+ * In the future, we may want to expand
+ * the storage array and continue
+ */
+ return (EINVAL);
+ }
+ vmap = (nxge_param_map_t *)&cfg_value;
+ if ((vmap->param_id) &&
+ (vmap->param_id < NXGE_MAX_VLANS) &&
+ (vmap->map_to < p_cfgp->max_rdc_grpids)) {
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_set_vlan_rdcgrp mapping"
+ " id %d grp %d",
+ vmap->param_id, vmap->map_to));
+ val_ptr = (uint32_t *)pa->value;
+ old_val_ptr = (uint32_t *)pa->old_value;
+
+ /* search to see if this vlan id is already configured */
+ for (i = 0; i < cfgd_vlans; i++) {
+ old_map = (nxge_param_map_t *)&val_ptr[i];
+ if ((old_map->param_id == 0) ||
+ (vmap->param_id == old_map->param_id) ||
+ (vlan_tbl[vmap->param_id].flag)) {
+ cfg_position = i;
+ break;
+ }
+ }
+
+ if (cfgd_vlans == 0) {
+ cfg_position = 0;
+ inc++;
+ }
+
+ if (i == cfgd_vlans) {
+ cfg_position = i;
+ inc++;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD2_CTL,
+ " set_vlan_rdcgrp mapping"
+ " i %d cfgd_vlans %llx position %d ",
+ i, cfgd_vlans, cfg_position));
+ if (val_ptr[cfg_position] != cfg_value) {
+ old_val_ptr[cfg_position] = val_ptr[cfg_position];
+ val_ptr[cfg_position] = cfg_value;
+ vlan_tbl[vmap->param_id].mpr_npr = vmap->pref;
+ vlan_tbl[vmap->param_id].flag = 1;
+ vlan_tbl[vmap->param_id].rdctbl =
+ vmap->map_to + p_cfgp->start_rdc_grpid;
+ cfg_it = B_TRUE;
+ if (inc) {
+ cfgd_vlans++;
+ pa->type &= ~NXGE_PARAM_ARRAY_CNT_MASK;
+ pa->type |= (cfgd_vlans <<
+ NXGE_PARAM_ARRAY_CNT_SHIFT);
+
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD2_CTL,
+ " after: param_set_vlan_rdcgrp "
+ " cfg_vlans %llx position %d \n",
+ cfgd_vlans, cfg_position));
+ }
+
+ } else {
+ return (EINVAL);
+ }
+
+ if (cfg_it == B_TRUE) {
+ status = nxge_fflp_config_vlan_table(nxgep,
+ (uint16_t)vmap->param_id);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_vlan_rdcgrp"));
+ return (0);
+}
+
+
+
+
+
+/* ARGSUSED */
+static int
+nxge_param_get_vlan_rdcgrp(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int i;
+ uint32_t *val_ptr;
+ nxge_param_map_t *vmap;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint64_t cfgd_vlans = 0;
+ nxge_mv_cfg_t *vlan_tbl;
+
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_SIZE * 32;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_vlan_rdcgrp "));
+ (void) mi_mpprintf(mp,
+ "VLAN RDC Mapping Information for Port\t %d \n",
+ nxgep->function_num);
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ buf_len = buff_alloc_size;
+ mp->b_cont = np;
+ cfgd_vlans = (pa->type & NXGE_PARAM_ARRAY_CNT_MASK) >>
+ NXGE_PARAM_ARRAY_CNT_SHIFT;
+
+ i = (int)cfgd_vlans;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ vlan_tbl = (nxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "Configured VLANs %d\n"
+ "VLAN ID\t RDC GRP (Actual/Port)\t"
+ " Prefernce\n", i);
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+
+ val_ptr = (uint32_t *)pa->value;
+
+ for (i = 0; i < cfgd_vlans; i++) {
+ vmap = (nxge_param_map_t *)&val_ptr[i];
+ if (p_class_cfgp->vlan_tbl[vmap->param_id].flag) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len,
+ " %d\t\t %d/%d\t\t %d\n",
+ vmap->param_id,
+ vlan_tbl[vmap->param_id].rdctbl,
+ vlan_tbl[vmap->param_id].rdctbl -
+ p_cfgp->start_rdc_grpid,
+ vlan_tbl[vmap->param_id].mpr_npr);
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_vlan_rdcgrp"));
+ return (0);
+}
+
+
+
+/* ARGSUSED */
+static int
+nxge_param_get_mac_rdcgrp(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int i;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ nxge_mv_cfg_t *mac_host_info;
+
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_SIZE * 32;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_mac_rdcgrp "));
+ (void) mi_mpprintf(mp,
+ " MAC ADDR RDC Mapping Information for Port\t %d\n",
+ nxgep->function_num);
+
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+
+ buf_len = buff_alloc_size;
+ mp->b_cont = np;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ mac_host_info = (nxge_mv_cfg_t *)&p_class_cfgp->mac_host_info[0];
+ print_len = snprintf((char *)np->b_wptr, buf_len,
+ "MAC ID\t RDC GRP (Actual/Port)\t"
+ " Prefernce\n");
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ for (i = 0; i < p_cfgp->max_macs; i++) {
+ if (mac_host_info[i].flag) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr,
+ buf_len,
+ " %d\t %d/%d\t\t %d\n",
+ i,
+ mac_host_info[i].rdctbl,
+ mac_host_info[i].rdctbl -
+ p_cfgp->start_rdc_grpid,
+ mac_host_info[i].mpr_npr);
+
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ }
+ }
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "Done Info Dumping \n");
+ ((mblk_t *)np)->b_wptr += print_len;
+ buf_len -= print_len;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_macrdcgrp"));
+ return (0);
+}
+
+
+
+/* ARGSUSED */
+static int
+nxge_param_tcam_enable(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ char *end;
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_tcam_enable"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_BINARY);
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ if (pa->value)
+ status = nxge_fflp_config_tcam_enable(nxgep);
+ else
+ status = nxge_fflp_config_tcam_disable(nxgep);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " <== nxge_param_tcam_enable"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_hash_lookup_enable(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ char *end;
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_hash_lookup_enable"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_BINARY);
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ if (pa->value)
+ status = nxge_fflp_config_hash_lookup_enable(nxgep);
+ else
+ status = nxge_fflp_config_hash_lookup_disable(nxgep);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " <== nxge_param_hash_lookup_enable"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_llc_snap_enable(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_llc_snap_enable"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_BINARY);
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ if (pa->value)
+ status = nxge_fflp_config_tcam_enable(nxgep);
+ else
+ status = nxge_fflp_config_tcam_disable(nxgep);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " <== nxge_param_llc_snap_enable"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+
+static int
+nxge_param_set_ether_usr(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint8_t ether_class;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint8_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_ether_usr"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ /* do the actual hw setup */
+ if (cfg_it == B_TRUE) {
+ ether_class = mi_strtol(pa->name, &end, 10);
+#ifdef lint
+ ether_class = ether_class;
+#endif
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " nxge_param_set_ether_usr"));
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_ether_usr"));
+ return (status);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_set_ip_usr(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ tcam_class_t class;
+ uint32_t status, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_ip_usr"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ /* do the actual hw setup with cfg_value. */
+ if (cfg_it == B_TRUE) {
+ class = mi_strtol(pa->name, &end, 10);
+ status = nxge_fflp_ip_usr_class_config(nxgep, class, pa->value);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_ip_usr"));
+ return (status);
+}
+
+static int
+nxge_class_name_2value(p_nxge_t nxgep, char *name)
+{
+ int i;
+ int class_instance = param_class_opt_ip_usr4;
+ p_nxge_param_t param_arr;
+ param_arr = nxgep->param_arr;
+ for (i = TCAM_CLASS_IP_USER_4; i <= TCAM_CLASS_SCTP_IPV6; i++) {
+ if (strcmp(param_arr[class_instance].name, name) == 0)
+ return (i);
+ class_instance++;
+ }
+ return (-1);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_set_ip_opt(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ tcam_class_t class;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_ip_opt"));
+
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ /* do the actual hw setup */
+ class = nxge_class_name_2value(nxgep, pa->name);
+ if (class == -1)
+ return (EINVAL);
+
+ status = nxge_fflp_ip_class_config(nxgep, class, pa->value);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_ip_opt"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_get_ip_opt(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, caddr_t cp)
+{
+ uint32_t status, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ tcam_class_t class;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_ip_opt"));
+
+ /* do the actual hw setup */
+ class = nxge_class_name_2value(nxgep, pa->name);
+ if (class == -1)
+ return (EINVAL);
+ cfg_value = 0;
+ status = nxge_fflp_ip_class_config_get(nxgep, class, &cfg_value);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ "nxge_param_get_ip_opt_get %x ", cfg_value));
+ pa->value = cfg_value;
+
+ (void) mi_mpprintf(mp, "%x", cfg_value);
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_ip_opt status "));
+ return (0);
+}
+
+
+/* ARGSUSED */
+static int
+nxge_param_fflp_hash_init(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ tcam_class_t class;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_fflp_hash_init"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_fflp_hash_init value %x",
+ cfg_value));
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+
+ if (cfg_it == B_TRUE) {
+ char *h_name;
+ /* do the actual hw setup */
+ h_name = pa->name;
+ h_name++;
+ class = mi_strtol(h_name, &end, 10);
+ switch (class) {
+ case 1:
+ status = nxge_fflp_set_hash1(nxgep,
+ (uint32_t)pa->value);
+ break;
+
+ case 2:
+ status = nxge_fflp_set_hash2(nxgep,
+ (uint16_t)pa->value);
+ break;
+
+ default:
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_fflp_hash_init"
+ " %s Wrong hash var %d",
+ pa->name, class));
+ return (EINVAL);
+ }
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " <== nxge_param_fflp_hash_init"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+
+static int
+nxge_param_set_grp_rdc(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+ int rdc_grp;
+ uint8_t real_rdc;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_grp_rdc"));
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_ANY);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+ if (cfg_value >= p_cfgp->max_rdcs) {
+ return (EINVAL);
+ }
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ char *grp_name;
+ grp_name = pa->name;
+ grp_name += strlen("default-grp");
+ rdc_grp = mi_strtol(grp_name, &end, 10);
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[rdc_grp];
+ real_rdc = rdc_grp_p->start_rdc + cfg_value;
+ if (nxge_check_rxdma_rdcgrp_member(nxgep, rdc_grp,
+ cfg_value) == B_FALSE) {
+ pa->value = pa->old_value;
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_set_grp_rdc"
+ " %d read %d actual %d outof range",
+ rdc_grp, cfg_value, real_rdc));
+ return (EINVAL);
+ }
+ status = nxge_rxdma_cfg_rdcgrp_default_rdc(nxgep, rdc_grp,
+ real_rdc);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_grp_rdc"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_set_port_rdc(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = B_TRUE, cfg_value;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_port_rdc"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ cfg_value = (uint32_t)mi_strtol(value, &end, BASE_ANY);
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ return (EINVAL);
+ }
+ if (pa->value != cfg_value) {
+ if (cfg_value >= p_cfgp->max_rdcs)
+ return (EINVAL);
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ status = nxge_rxdma_cfg_port_default_rdc(nxgep,
+ nxgep->function_num,
+ nxgep->rdc[cfg_value]);
+ if (status != NXGE_OK)
+ return (EINVAL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_port_rdc"));
+ return (0);
+}
+
+
+
+/* ARGSUSED */
+
+static int
+nxge_param_set_nxge_debug_flag(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0;
+ uint64_t cfg_value = 0;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_nxge_debug_flag"));
+ cfg_value = mi_strtol(value, &end, BASE_HEX);
+
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL,
+ " nxge_param_set_nxge_debug_flag"
+ " outof range %llx", cfg_value));
+ return (EINVAL);
+ }
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ nxgep->nxge_debug_level = pa->value;
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_nxge_debug_flag"));
+ return (status);
+}
+
+
+/* ARGSUSED */
+static int
+nxge_param_get_debug_flag(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ int status = 0;
+ p_nxge_param_t pa = (p_nxge_param_t)cp;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_get_debug_flag"));
+
+ if (pa->value > 0xffffffff)
+ (void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32),
+ (int)(pa->value & 0xffffffff));
+ else
+ (void) mi_mpprintf(mp, "%x", (int)pa->value);
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_get_debug_flag"));
+ return (status);
+}
+
+/* ARGSUSED */
+
+static int
+nxge_param_set_npi_debug_flag(p_nxge_t nxgep, queue_t *q,
+ mblk_t *mp, char *value, caddr_t cp)
+{
+ char *end;
+ uint32_t status = 0;
+ uint64_t cfg_value = 0;
+ p_nxge_param_t pa;
+ uint32_t cfg_it = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_set_npi_debug_flag"));
+ cfg_value = mi_strtol(value, &end, BASE_HEX);
+ pa = (p_nxge_param_t)cp;
+ if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) {
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, " nxge_param_set_npi_debug_flag"
+ " outof range %llx", cfg_value));
+ return (EINVAL);
+ }
+ if (pa->value != cfg_value) {
+ pa->old_value = pa->value;
+ pa->value = cfg_value;
+ cfg_it = B_TRUE;
+ }
+
+ if (cfg_it == B_TRUE) {
+ npi_debug_level = pa->value;
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_set_debug_flag"));
+ return (status);
+}
+
+
+/* ARGSUSED */
+
+
+
+/* ARGSUSED */
+static int
+nxge_param_dump_rdc(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t rdc;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_rdc"));
+
+ (void) npi_rxdma_dump_fzc_regs(NXGE_DEV_NPI_HANDLE(nxgep));
+
+ for (rdc = 0; rdc < nxgep->nrdc; rdc++)
+ (void) nxge_dump_rxdma_channel(nxgep, nxgep->rdc[rdc]);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_rdc"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_dump_tdc(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t tdc;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_tdc"));
+
+ for (tdc = 0; tdc < nxgep->ntdc; tdc++)
+ (void) nxge_txdma_regs_dump(nxgep, nxgep->tdc[tdc]);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_tdc"));
+ return (0);
+}
+
+
+/* ARGSUSED */
+static int
+nxge_param_dump_fflp_regs(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_fflp_regs"));
+
+ (void) npi_fflp_dump_regs(NXGE_DEV_NPI_HANDLE(nxgep));
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_fflp_regs"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_dump_mac_regs(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_mac_regs"));
+
+ (void) npi_mac_dump_regs(NXGE_DEV_NPI_HANDLE(nxgep),
+ nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_mac_regs"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_dump_ipp_regs(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_ipp_regs"));
+
+ (void) (void) npi_ipp_dump_regs(NXGE_DEV_NPI_HANDLE(nxgep),
+ nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_ipp_regs"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_dump_vlan_table(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_dump_vlan_table"));
+
+ (void) npi_fflp_vlan_tbl_dump(NXGE_DEV_NPI_HANDLE(nxgep));
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_dump_vlan_table"));
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+nxge_param_dump_rdc_table(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint8_t table;
+
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "==> nxge_param_dump_rdc_table"));
+ for (table = 0; table < NXGE_MAX_RDC_GROUPS; table++) {
+ (void) npi_rxdma_dump_rdc_table(NXGE_DEV_NPI_HANDLE(nxgep),
+ table);
+ }
+ NXGE_DEBUG_MSG((nxgep, NDD_CTL, "<== nxge_param_dump_rdc_table"));
+ return (0);
+}
+
+
+typedef struct block_info {
+ char *name;
+ uint32_t offset;
+} block_info_t;
+
+block_info_t reg_block[] = {
+ {"PIO", PIO},
+ {"FZC_PIO", FZC_PIO},
+ {"FZC_XMAC", FZC_MAC},
+ {"FZC_IPP", FZC_IPP},
+ {"FFLP", FFLP},
+ {"FZC_FFLP", FZC_FFLP},
+ {"PIO_VADDR", PIO_VADDR},
+ {"ZCP", ZCP},
+ {"FZC_ZCP", FZC_ZCP},
+ {"DMC", DMC},
+ {"FZC_DMC", FZC_DMC},
+ {"TXC", TXC},
+ {"FZC_TXC", FZC_TXC},
+ {"PIO_LDSV", PIO_LDSV},
+ {"PIO_LDGIM", PIO_LDGIM},
+ {"PIO_IMASK0", PIO_IMASK0},
+ {"PIO_IMASK1", PIO_IMASK1},
+ {"FZC_PROM", FZC_PROM},
+ {"END", ALL_FF_32},
+};
+
+/* ARGSUSED */
+static int
+nxge_param_dump_ptrs(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t cp)
+{
+
+ uint_t print_len, buf_len;
+ p_mblk_t np;
+ int rdc, tdc, block;
+ uint64_t base;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int buff_alloc_size = NXGE_NDD_INFODUMP_BUFF_8K;
+ p_tx_ring_t *tx_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_dump_ptrs"));
+
+ (void) mi_mpprintf(mp,
+ "ptr information for Port\t %d \n",
+ nxgep->function_num);
+
+
+ if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) {
+ /* The following may work even if we cannot get a large buf. */
+ (void) mi_mpprintf(mp, "%s\n", "out of buffer");
+ return (0);
+ }
+
+ buf_len = buff_alloc_size;
+
+ mp->b_cont = np;
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "nxgep (nxge_t) $%p\n"
+ "dev_regs (dev_regs_t) $%p\n",
+ nxgep, nxgep->dev_regs);
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ /* do register pointers */
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "reg base (npi_reg_ptr_t) $%p\t "
+ "pci reg (npi_reg_ptr_t) $%p\n",
+ nxgep->dev_regs->nxge_regp,
+ nxgep->dev_regs->nxge_pciregp);
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "\nBlock \t Offset \n");
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ block = 0;
+ base = (uint64_t)nxgep->dev_regs->nxge_regp;
+ while (reg_block[block].offset != ALL_FF_32) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "%9s\t 0x%llx\n",
+ reg_block[block].name,
+ (unsigned long long)(reg_block[block].offset +
+ base));
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ block++;
+ }
+
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "\nRDC\t rcrp (rx_rcr_ring_t)\t "
+ "rbrp (rx_rbr_ring_t)\n");
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+
+ for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ " %d\t $%p\t\t $%p\n",
+ rdc, rcr_rings[rdc],
+ rbr_rings[rdc]);
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ }
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "\nTDC\t tdcp (tx_ring_t)\n");
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ tx_rings = nxgep->tx_rings->rings;
+ for (tdc = 0; tdc < p_cfgp->max_tdcs; tdc++) {
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ " %d\t $%p\n",
+ tdc, tx_rings[tdc]);
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+ }
+
+ print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len,
+ "\n\n");
+
+ ADVANCE_PRINT_BUFFER(np, print_len, buf_len);
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_dump_ptrs"));
+ return (0);
+}
+
+
+
+/*
+ * Load 'name' into the named dispatch table pointed to by 'ndp'.
+ * 'ndp' should be the address of a char pointer cell. If the table
+ * does not exist (*ndp == 0), a new table is allocated and 'ndp'
+ * is stuffed. If there is not enough space in the table for a new
+ * entry, more space is allocated.
+ */
+boolean_t
+nxge_nd_load(caddr_t *pparam, char *name,
+ pfi_t get_pfi, pfi_t set_pfi, caddr_t data)
+{
+ ND *nd;
+ NDE *nde;
+
+ NXGE_DEBUG_MSG((NULL, NDD2_CTL, " ==> nxge_nd_load"));
+ if (!pparam)
+ return (B_FALSE);
+ if ((nd = (ND *)*pparam) == NULL) {
+ if ((nd = (ND *)KMEM_ZALLOC(sizeof (ND), KM_NOSLEEP))
+ == NULL)
+ return (B_FALSE);
+ *pparam = (caddr_t)nd;
+ }
+ if (nd->nd_tbl) {
+ for (nde = nd->nd_tbl; nde->nde_name; nde++) {
+ if (strcmp(name, nde->nde_name) == 0)
+ goto fill_it;
+ }
+ }
+ if (nd->nd_free_count <= 1) {
+ if ((nde = (NDE *)KMEM_ZALLOC(nd->nd_size +
+ NDE_ALLOC_SIZE, KM_NOSLEEP)) == NULL)
+ return (B_FALSE);
+ nd->nd_free_count += NDE_ALLOC_COUNT;
+ if (nd->nd_tbl) {
+ bcopy((char *)nd->nd_tbl, (char *)nde, nd->nd_size);
+ KMEM_FREE((char *)nd->nd_tbl, nd->nd_size);
+ } else {
+ nd->nd_free_count--;
+ nde->nde_name = "?";
+ nde->nde_get_pfi = nxge_nd_get_names;
+ nde->nde_set_pfi = nxge_set_default;
+ }
+ nde->nde_data = (caddr_t)nd;
+ nd->nd_tbl = nde;
+ nd->nd_size += NDE_ALLOC_SIZE;
+ }
+ for (nde = nd->nd_tbl; nde->nde_name; nde++)
+ noop;
+ nd->nd_free_count--;
+fill_it:
+ nde->nde_name = name;
+ nde->nde_get_pfi = get_pfi;
+ nde->nde_set_pfi = set_pfi;
+ nde->nde_data = data;
+ NXGE_DEBUG_MSG((NULL, NDD2_CTL, " <== nxge_nd_load"));
+
+ return (B_TRUE);
+}
+
+/*
+ * Free the table pointed to by 'pparam'
+ */
+void
+nxge_nd_free(caddr_t *pparam)
+{
+ ND *nd;
+
+ if ((nd = (ND *)*pparam) != NULL) {
+ if (nd->nd_tbl)
+ KMEM_FREE((char *)nd->nd_tbl, nd->nd_size);
+ KMEM_FREE((char *)nd, sizeof (ND));
+ *pparam = nil(caddr_t);
+ }
+}
+
+int
+nxge_nd_getset(p_nxge_t nxgep, queue_t *q, caddr_t param, p_mblk_t mp)
+{
+ int err;
+ IOCP iocp;
+ p_mblk_t mp1, mp2;
+ ND *nd;
+ NDE *nde;
+ char *valp;
+ size_t avail;
+
+ if (!param) {
+ return (B_FALSE);
+ }
+ nd = (ND *)param;
+ iocp = (IOCP)mp->b_rptr;
+ if ((iocp->ioc_count == 0) || !(mp1 = mp->b_cont)) {
+ mp->b_datap->db_type = M_IOCACK;
+ iocp->ioc_count = 0;
+ iocp->ioc_error = EINVAL;
+ return (B_FALSE);
+ }
+ /*
+ * NOTE - logic throughout nd_xxx assumes single data block for ioctl.
+ * However, existing code sends in some big buffers.
+ */
+ avail = iocp->ioc_count;
+ if (mp1->b_cont) {
+ freemsg(mp1->b_cont);
+ mp1->b_cont = NULL;
+ }
+
+ mp1->b_datap->db_lim[-1] = '\0'; /* Force null termination */
+ for (valp = (char *)mp1->b_rptr; *valp != '\0'; valp++) {
+ if (*valp == '-')
+ *valp = '_';
+ }
+
+ valp = (char *)mp1->b_rptr;
+
+ for (nde = nd->nd_tbl; /* */; nde++) {
+ if (!nde->nde_name)
+ return (B_FALSE);
+ if (strcmp(nde->nde_name, valp) == 0)
+ break;
+ }
+ err = EINVAL;
+ while (*valp++)
+ noop;
+ if (!*valp || valp >= (char *)mp1->b_wptr)
+ valp = nilp(char);
+ switch (iocp->ioc_cmd) {
+ case ND_GET:
+ /*
+ * (temporary) hack: "*valp" is size of user buffer for
+ * copyout. If result of action routine is too big, free
+ * excess and return ioc_rval as buffer size needed.
+ * Return as many mblocks as will fit, free the rest. For
+ * backward compatibility, assume size of original ioctl
+ * buffer if "*valp" bad or not given.
+ */
+ if (valp)
+ avail = mi_strtol(valp, (char **)0, 10);
+ /*
+ * We overwrite the name/value with the reply data
+ */
+ mp2 = mp1;
+ while (mp2) {
+ mp2->b_wptr = mp2->b_rptr;
+ mp2 = mp2->b_cont;
+ }
+
+ err = (*nde->nde_get_pfi)(nxgep, q, mp1, nde->nde_data);
+
+ if (!err) {
+ size_t size_out = 0;
+ size_t excess;
+
+ iocp->ioc_rval = 0;
+
+ /* Tack on the null */
+ err = nxge_mk_mblk_tail_space(mp1, &mp2, 1);
+ if (!err) {
+ *mp2->b_wptr++ = '\0';
+ size_out = msgdsize(mp1);
+ excess = size_out - avail;
+ if (excess > 0) {
+ iocp->ioc_rval = (int)size_out;
+ size_out -= excess;
+ (void) adjmsg(mp1, -(excess + 1));
+ err = nxge_mk_mblk_tail_space(
+ mp1, &mp2, 1);
+ if (!err)
+ *mp2->b_wptr++ = '\0';
+ else
+ size_out = 0;
+ }
+ } else
+ size_out = 0;
+ iocp->ioc_count = size_out;
+ }
+ break;
+
+ case ND_SET:
+ if (valp) {
+ if (nde->nde_set_pfi) {
+ err = (*nde->nde_set_pfi)(nxgep, q, mp1, valp,
+ nde->nde_data);
+ iocp->ioc_count = 0;
+ freemsg(mp1);
+ mp->b_cont = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ iocp->ioc_error = err;
+ mp->b_datap->db_type = M_IOCACK;
+ return (B_TRUE);
+}
+
+/* ARGSUSED */
+int
+nxge_nd_get_names(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t param)
+{
+ ND *nd;
+ NDE *nde;
+ char *rwtag;
+ boolean_t get_ok, set_ok;
+ size_t param_len;
+ int status = 0;
+
+ nd = (ND *)param;
+ if (!nd)
+ return (ENOENT);
+
+ for (nde = nd->nd_tbl; nde->nde_name; nde++) {
+ get_ok = (nde->nde_get_pfi != nxge_get_default) &&
+ (nde->nde_get_pfi != NULL);
+ set_ok = (nde->nde_set_pfi != nxge_set_default) &&
+ (nde->nde_set_pfi != NULL);
+ if (get_ok) {
+ if (set_ok)
+ rwtag = "read and write";
+ else
+ rwtag = "read only";
+ } else if (set_ok)
+ rwtag = "write only";
+ else {
+ continue;
+ }
+ param_len = strlen(rwtag);
+ param_len += strlen(nde->nde_name);
+ param_len += 4;
+
+ (void) mi_mpprintf(mp, "%s (%s)", nde->nde_name, rwtag);
+ }
+ return (status);
+}
+
+/* ARGSUSED */
+int
+nxge_get_default(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, caddr_t data)
+
+{
+ return (EACCES);
+}
+
+/* ARGSUSED */
+int
+
+nxge_set_default(p_nxge_t nxgep, queue_t *q, p_mblk_t mp, char *value,
+ caddr_t data)
+
+{
+ return (EACCES);
+}
+
+
+void
+nxge_param_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
+{
+ int cmd;
+ int status = B_FALSE;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_ioctl"));
+ cmd = iocp->ioc_cmd;
+ switch (cmd) {
+ default:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "nxge_param_ioctl: bad cmd 0x%0x", cmd));
+ break;
+
+ case ND_GET:
+ case ND_SET:
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "nxge_param_ioctl: cmd 0x%0x", cmd));
+ if (!nxge_nd_getset(nxgep, wq, nxgep->param_list, mp)) {
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL,
+ "false ret from nxge_nd_getset"));
+ break;
+ }
+ status = B_TRUE;
+ break;
+ }
+
+ if (status) {
+ qreply(wq, mp);
+ } else {
+ miocnak(wq, mp, 0, EINVAL);
+ }
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_param_ioctl"));
+}
+
+/* ARGSUSED */
+static boolean_t
+nxge_param_link_update(p_nxge_t nxgep)
+{
+ p_nxge_param_t param_arr;
+ nxge_param_index_t i;
+ boolean_t update_xcvr;
+ boolean_t update_dev;
+ int instance;
+ boolean_t status = B_TRUE;
+
+ NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_param_link_update"));
+
+ param_arr = nxgep->param_arr;
+ instance = nxgep->instance;
+ update_xcvr = B_FALSE;
+ for (i = param_anar_1000fdx; i < param_anar_asmpause; i++) {
+ update_xcvr |= param_arr[i].value;
+ }
+
+ if (update_xcvr) {
+ update_xcvr = B_FALSE;
+ for (i = param_autoneg; i < param_enable_ipg0; i++) {
+ update_xcvr |=
+ (param_arr[i].value != param_arr[i].old_value);
+ param_arr[i].old_value = param_arr[i].value;
+ }
+ if (update_xcvr) {
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_link_init(nxgep);
+ (void) nxge_mac_init(nxgep);
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+ RW_EXIT(&nxgep->filter_lock);
+ }
+ } else {
+ cmn_err(CE_WARN, " Last setting will leave nxge%d with "
+ " no link capabilities.", instance);
+ cmn_err(CE_WARN, " Restoring previous setting.");
+ for (i = param_anar_1000fdx; i < param_anar_asmpause; i++)
+ param_arr[i].value = param_arr[i].old_value;
+
+ }
+ update_dev = B_FALSE;
+
+ if (update_dev) {
+ RW_ENTER_WRITER(&nxgep->filter_lock);
+ (void) nxge_rx_mac_disable(nxgep);
+ (void) nxge_tx_mac_disable(nxgep);
+ (void) nxge_set_dev_params(nxgep);
+
+ (void) nxge_tx_mac_enable(nxgep);
+ (void) nxge_rx_mac_enable(nxgep);
+ RW_EXIT(&nxgep->filter_lock);
+ }
+
+nxge_param_hw_update_exit:
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_param_link_update status = 0x%08x", status));
+ return (status);
+}
+
+
+
+/* ARGSUSED */
+static void
+nxge_set_dev_params(p_nxge_t nxgep)
+{
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_dev_params"));
+
+ /* Reinitialize any instance specific parameters. */
+
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_rxdma.c b/usr/src/uts/sun4v/io/nxge/nxge_rxdma.c
new file mode 100644
index 0000000000..794aa5541b
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_rxdma.c
@@ -0,0 +1,4873 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/nxge/nxge_rxdma.h>
+
+#define NXGE_ACTUAL_RDCGRP(nxgep, rdcgrp) \
+ (rdcgrp + nxgep->pt_config.hw_config.start_rdc_grpid)
+#define NXGE_ACTUAL_RDC(nxgep, rdc) \
+ (rdc + nxgep->pt_config.hw_config.start_rdc)
+
+/*
+ * Globals: tunable parameters (/etc/system or adb)
+ *
+ */
+extern uint32_t nxge_rbr_size;
+extern uint32_t nxge_rcr_size;
+extern uint32_t nxge_rbr_spare_size;
+
+extern uint32_t nxge_mblks_pending;
+
+/*
+ * Tunable to reduce the amount of time spent in the
+ * ISR doing Rx Processing.
+ */
+extern uint32_t nxge_max_rx_pkts;
+boolean_t nxge_jumbo_enable;
+
+/*
+ * Tunables to manage the receive buffer blocks.
+ *
+ * nxge_rx_threshold_hi: copy all buffers.
+ * nxge_rx_bcopy_size_type: receive buffer block size type.
+ * nxge_rx_threshold_lo: copy only up to tunable block size type.
+ */
+extern nxge_rxbuf_threshold_t nxge_rx_threshold_hi;
+extern nxge_rxbuf_type_t nxge_rx_buf_size_type;
+extern nxge_rxbuf_threshold_t nxge_rx_threshold_lo;
+
+#if !defined(_BIG_ENDIAN)
+#define RDC_NPI_DIRECT
+#endif
+
+#define USE_DYNAMIC_BLANKING
+
+#ifdef USE_DYNAMIC_BLANKING
+uint16_t nxge_rx_intr_timeout = 0x8008;
+#endif
+
+#ifdef RX_USE_RECLAIM_POST
+#define RX_POST_PKTS 8
+#endif
+
+
+static nxge_status_t nxge_map_rxdma(p_nxge_t);
+static void nxge_unmap_rxdma(p_nxge_t);
+
+static nxge_status_t nxge_rxdma_hw_start_common(p_nxge_t);
+static void nxge_rxdma_hw_stop_common(p_nxge_t);
+
+static nxge_status_t nxge_rxdma_hw_start(p_nxge_t);
+static void nxge_rxdma_hw_stop(p_nxge_t);
+
+static nxge_status_t nxge_map_rxdma_channel(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, p_rx_rbr_ring_t *,
+ uint32_t,
+ p_nxge_dma_common_t *, p_rx_rcr_ring_t *,
+ p_rx_mbox_t *);
+static void nxge_unmap_rxdma_channel(p_nxge_t, uint16_t,
+ p_rx_rbr_ring_t, p_rx_rcr_ring_t, p_rx_mbox_t);
+
+static nxge_status_t nxge_map_rxdma_channel_cfg_ring(p_nxge_t,
+ uint16_t,
+ p_nxge_dma_common_t *, p_rx_rbr_ring_t *,
+ p_rx_rcr_ring_t *, p_rx_mbox_t *);
+static void nxge_unmap_rxdma_channel_cfg_ring(p_nxge_t,
+ p_rx_rcr_ring_t, p_rx_mbox_t);
+
+static nxge_status_t nxge_map_rxdma_channel_buf_ring(p_nxge_t,
+ uint16_t,
+ p_nxge_dma_common_t *,
+ p_rx_rbr_ring_t *, uint32_t);
+static void nxge_unmap_rxdma_channel_buf_ring(p_nxge_t,
+ p_rx_rbr_ring_t);
+
+static nxge_status_t nxge_rxdma_start_channel(p_nxge_t, uint16_t,
+ p_rx_rbr_ring_t, p_rx_rcr_ring_t, p_rx_mbox_t);
+static nxge_status_t nxge_rxdma_stop_channel(p_nxge_t, uint16_t);
+
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+mblk_t *
+nxge_rx_pkts(p_nxge_t, uint_t, p_nxge_ldv_t,
+ p_rx_rcr_ring_t *, rx_dma_ctl_stat_t);
+#else
+mblk_t *
+nxge_rx_pkts(p_nxge_t, uint_t, p_nxge_ldv_t, p_rx_rcr_ring_t *);
+#endif
+
+static void nxge_receive_packet(p_nxge_t,
+ p_rx_rcr_ring_t,
+ p_rcr_entry_t,
+ boolean_t *,
+ mblk_t **, mblk_t **);
+
+nxge_status_t nxge_disable_rxdma_channel(p_nxge_t, uint16_t);
+
+static p_rx_msg_t nxge_allocb(size_t, uint32_t, p_nxge_dma_common_t);
+static void nxge_freeb(p_rx_msg_t);
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+static void nxge_rx_pkts_vring(p_nxge_t, uint_t,
+ p_nxge_ldv_t, rx_dma_ctl_stat_t);
+#else
+static void nxge_rx_pkts_vring(p_nxge_t, uint_t, p_nxge_ldv_t);
+#endif
+static nxge_status_t nxge_rx_err_evnts(p_nxge_t, uint_t,
+ p_nxge_ldv_t, rx_dma_ctl_stat_t);
+
+static nxge_status_t nxge_rxdma_handle_port_errors(p_nxge_t,
+ uint32_t, uint32_t);
+
+static nxge_status_t nxge_rxbuf_index_info_init(p_nxge_t,
+ p_rx_rbr_ring_t);
+
+
+static nxge_status_t
+nxge_rxdma_fatal_err_recover(p_nxge_t, uint16_t);
+
+nxge_status_t
+nxge_rx_port_fatal_err_recover(p_nxge_t);
+
+
+nxge_status_t
+nxge_init_rxdma_channels(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_init_rxdma_channels"));
+
+ status = nxge_map_rxdma(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_rxdma: status 0x%x", status));
+ return (status);
+ }
+
+ status = nxge_rxdma_hw_start_common(nxgep);
+ if (status != NXGE_OK) {
+ nxge_unmap_rxdma(nxgep);
+ }
+
+ status = nxge_rxdma_hw_start(nxgep);
+ if (status != NXGE_OK) {
+ nxge_unmap_rxdma(nxgep);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_init_rxdma_channels: status 0x%x", status));
+
+ return (status);
+}
+
+void
+nxge_uninit_rxdma_channels(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_uninit_rxdma_channels"));
+
+ nxge_rxdma_hw_stop(nxgep);
+ nxge_rxdma_hw_stop_common(nxgep);
+ nxge_unmap_rxdma(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_uinit_rxdma_channels"));
+}
+
+
+nxge_status_t
+nxge_reset_rxdma_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_reset_rxdma_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_rxdma_cfg_rdc_reset(handle, channel);
+
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ return (status);
+}
+
+void
+nxge_rxdma_regs_dump_channels(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_regs_dump_channels"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_rxdma_dump_fzc_regs(handle);
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ if (rx_rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_regs_dump_channels: "
+ "NULL ring pointer"));
+ return;
+ }
+ if (rx_rbr_rings->rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_regs_dump_channels: "
+ " NULL rbr rings pointer"));
+ return;
+ }
+
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_regs_dump_channels: no channel"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_regs_dump_channels (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ for (i = 0; i < ndmas; i++) {
+ if (rbr_rings == NULL || rbr_rings[i] == NULL) {
+ continue;
+ }
+ channel = rbr_rings[i]->rdc;
+ (void) nxge_dump_rxdma_channel(nxgep, channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_regs_dump"));
+
+}
+
+nxge_status_t
+nxge_dump_rxdma_channel(p_nxge_t nxgep, uint8_t channel)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_dump_rxdma_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_rxdma_dump_rdc_regs(handle, channel);
+
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_dump_rxdma_channel"));
+ return (status);
+}
+
+nxge_status_t
+nxge_init_rxdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel,
+ p_rx_dma_ent_msk_t mask_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_rxdma_channel_event_mask"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_rxdma_event_mask(handle, OP_SET, channel, mask_p);
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ return (status);
+}
+
+nxge_status_t
+nxge_init_rxdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel,
+ p_rx_dma_ctl_stat_t cs_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_rxdma_channel_cntl_stat"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_rxdma_control_status(handle, OP_SET, channel, cs_p);
+
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ return (status);
+}
+
+nxge_status_t
+nxge_rxdma_cfg_rdcgrp_default_rdc(p_nxge_t nxgep, uint8_t rdcgrp,
+ uint8_t rdc)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+ uint8_t actual_rdcgrp, actual_rdc;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ " ==> nxge_rxdma_cfg_rdcgrp_default_rdc"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[rdcgrp];
+ rdc_grp_p->rdc[0] = rdc;
+
+ actual_rdcgrp = NXGE_ACTUAL_RDCGRP(nxgep, rdcgrp);
+ actual_rdc = NXGE_ACTUAL_RDC(nxgep, rdc);
+
+ rs = npi_rxdma_cfg_rdc_table_default_rdc(handle, actual_rdcgrp,
+ actual_rdc);
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ " <== nxge_rxdma_cfg_rdcgrp_default_rdc"));
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_rxdma_cfg_port_default_rdc(p_nxge_t nxgep, uint8_t port, uint8_t rdc)
+{
+ npi_handle_t handle;
+
+ uint8_t actual_rdc;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ " ==> nxge_rxdma_cfg_port_default_rdc"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ actual_rdc = NXGE_ACTUAL_RDC(nxgep, rdc);
+ rs = npi_rxdma_cfg_default_port_rdc(handle, port, actual_rdc);
+
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ " <== nxge_rxdma_cfg_port_default_rdc"));
+
+ return (NXGE_OK);
+}
+
+
+nxge_status_t
+nxge_rxdma_cfg_rcr_threshold(p_nxge_t nxgep, uint8_t channel,
+ uint16_t pkts)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ " ==> nxge_rxdma_cfg_rcr_threshold"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ rs = npi_rxdma_cfg_rdc_rcr_threshold(handle, channel, pkts);
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, " <== nxge_rxdma_cfg_rcr_threshold"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_rxdma_cfg_rcr_timeout(p_nxge_t nxgep, uint8_t channel,
+ uint16_t tout, uint8_t enable)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ npi_handle_t handle;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, " ==> nxge_rxdma_cfg_rcr_timeout"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if (enable == 0) {
+ rs = npi_rxdma_cfg_rdc_rcr_timeout_disable(handle, channel);
+ } else {
+ rs = npi_rxdma_cfg_rdc_rcr_timeout(handle, channel,
+ tout);
+ }
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, " <== nxge_rxdma_cfg_rcr_timeout"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_enable_rxdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p)
+{
+ npi_handle_t handle;
+ rdc_desc_cfg_t rdc_desc;
+ p_rcrcfig_b_t cfgb_p;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_enable_rxdma_channel"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Use configuration data composed at init time.
+ * Write to hardware the receive ring configurations.
+ */
+ rdc_desc.mbox_enable = 1;
+ rdc_desc.mbox_addr = mbox_p->mbox_addr;
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_enable_rxdma_channel: mboxp $%p($%p)",
+ mbox_p->mbox_addr, rdc_desc.mbox_addr));
+
+ rdc_desc.rbr_len = rbr_p->rbb_max;
+ rdc_desc.rbr_addr = rbr_p->rbr_addr;
+
+ switch (nxgep->rx_bksize_code) {
+ case RBR_BKSIZE_4K:
+ rdc_desc.page_size = SIZE_4KB;
+ break;
+ case RBR_BKSIZE_8K:
+ rdc_desc.page_size = SIZE_8KB;
+ break;
+ case RBR_BKSIZE_16K:
+ rdc_desc.page_size = SIZE_16KB;
+ break;
+ case RBR_BKSIZE_32K:
+ rdc_desc.page_size = SIZE_32KB;
+ break;
+ }
+
+ rdc_desc.size0 = rbr_p->npi_pkt_buf_size0;
+ rdc_desc.valid0 = 1;
+
+ rdc_desc.size1 = rbr_p->npi_pkt_buf_size1;
+ rdc_desc.valid1 = 1;
+
+ rdc_desc.size2 = rbr_p->npi_pkt_buf_size2;
+ rdc_desc.valid2 = 1;
+
+ rdc_desc.full_hdr = rcr_p->full_hdr_flag;
+ rdc_desc.offset = rcr_p->sw_priv_hdr_len;
+
+ rdc_desc.rcr_len = rcr_p->comp_size;
+ rdc_desc.rcr_addr = rcr_p->rcr_addr;
+
+ cfgb_p = &(rcr_p->rcr_cfgb);
+ rdc_desc.rcr_threshold = cfgb_p->bits.ldw.pthres;
+ rdc_desc.rcr_timeout = cfgb_p->bits.ldw.timeout;
+ rdc_desc.rcr_timeout_enable = cfgb_p->bits.ldw.entout;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_enable_rxdma_channel: "
+ "rbr_len qlen %d pagesize code %d rcr_len %d",
+ rdc_desc.rbr_len, rdc_desc.page_size, rdc_desc.rcr_len));
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_enable_rxdma_channel: "
+ "size 0 %d size 1 %d size 2 %d",
+ rbr_p->npi_pkt_buf_size0, rbr_p->npi_pkt_buf_size1,
+ rbr_p->npi_pkt_buf_size2));
+
+ rs = npi_rxdma_cfg_rdc_ring(handle, rbr_p->rdc, &rdc_desc);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /*
+ * Enable the timeout and threshold.
+ */
+ rs = npi_rxdma_cfg_rdc_rcr_threshold(handle, channel,
+ rdc_desc.rcr_threshold);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ rs = npi_rxdma_cfg_rdc_rcr_timeout(handle, channel,
+ rdc_desc.rcr_timeout);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Enable the DMA */
+ rs = npi_rxdma_cfg_rdc_enable(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Kick the DMA engine. */
+ npi_rxdma_rdc_rbr_kick(handle, channel, rbr_p->rbb_max);
+#ifdef RX_USE_RECLAIM_POST
+ rbr_p->msg_rd_index = rbr_p->rbb_max;
+ rbr_p->hw_freed = 0;
+ rbr_p->sw_freed = 0;
+#endif
+ /* Clear the rbr empty bit */
+ (void) npi_rxdma_channel_rbr_empty_clear(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_enable_rxdma_channel"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_disable_rxdma_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_disable_rxdma_channel"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ /* disable the DMA */
+ rs = npi_rxdma_cfg_rdc_disable(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_disable_rxdma_channel:failed (0x%x)",
+ rs));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_disable_rxdma_channel"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_rxdma_channel_rcrflush(p_nxge_t nxgep, uint8_t channel)
+{
+ npi_handle_t handle;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_rxdma_channel_rcrflush"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ npi_rxdma_rdc_rcr_flush(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "<== nxge_init_rxdma_channel_rcrflsh"));
+ return (status);
+
+}
+
+#define MID_INDEX(l, r) ((r + l + 1) >> 1)
+
+#define TO_LEFT -1
+#define TO_RIGHT 1
+#define BOTH_RIGHT (TO_RIGHT + TO_RIGHT)
+#define BOTH_LEFT (TO_LEFT + TO_LEFT)
+#define IN_MIDDLE (TO_RIGHT + TO_LEFT)
+#define NO_HINT 0xffffffff
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_rxbuf_pp_to_vp(p_nxge_t nxgep, p_rx_rbr_ring_t rbr_p,
+ uint8_t pktbufsz_type, uint64_t *pkt_buf_addr_pp,
+ uint64_t **pkt_buf_addr_p, uint32_t *bufoffset, uint32_t *msg_index)
+{
+ int bufsize;
+ uint64_t pktbuf_pp;
+ uint64_t dvma_addr;
+ rxring_info_t *ring_info;
+ int base_side, end_side;
+ int r_index, l_index, anchor_index;
+ int found, search_done;
+ uint32_t offset, chunk_size, block_size, page_size_mask;
+ uint32_t chunk_index, block_index, total_index;
+ int max_iterations, iteration;
+ rxbuf_index_info_t *bufinfo;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "==> nxge_rxbuf_pp_to_vp"));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: buf_pp $%p btype %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type));
+
+ pktbuf_pp = (uint64_t)pkt_buf_addr_pp;
+
+ switch (pktbufsz_type) {
+ case 0:
+ bufsize = rbr_p->pkt_buf_size0;
+ break;
+ case 1:
+ bufsize = rbr_p->pkt_buf_size1;
+ break;
+ case 2:
+ bufsize = rbr_p->pkt_buf_size2;
+ break;
+ case RCR_SINGLE_BLOCK:
+ bufsize = 0;
+ anchor_index = 0;
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+
+ if (rbr_p->num_blocks == 1) {
+ anchor_index = 0;
+ ring_info = rbr_p->ring_info;
+ bufinfo = (rxbuf_index_info_t *)ring_info->buffer;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (found, 1 block) "
+ "buf_pp $%p btype %d anchor_index %d "
+ "bufinfo $%p",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index,
+ bufinfo));
+
+ goto found_index;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: "
+ "buf_pp $%p btype %d anchor_index %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index));
+
+ ring_info = rbr_p->ring_info;
+ found = B_FALSE;
+ bufinfo = (rxbuf_index_info_t *)ring_info->buffer;
+ iteration = 0;
+ max_iterations = ring_info->max_iterations;
+ /*
+ * First check if this block have been seen
+ * recently. This is indicated by a hint which
+ * is initialized when the first buffer of the block
+ * is seen. The hint is reset when the last buffer of
+ * the block has been processed.
+ * As three block sizes are supported, three hints
+ * are kept. The idea behind the hints is that once
+ * the hardware uses a block for a buffer of that
+ * size, it will use it exclusively for that size
+ * and will use it until it is exhausted. It is assumed
+ * that there would a single block being used for the same
+ * buffer sizes at any given time.
+ */
+ if (ring_info->hint[pktbufsz_type] != NO_HINT) {
+ anchor_index = ring_info->hint[pktbufsz_type];
+ dvma_addr = bufinfo[anchor_index].dvma_addr;
+ chunk_size = bufinfo[anchor_index].buf_size;
+ if ((pktbuf_pp >= dvma_addr) &&
+ (pktbuf_pp < (dvma_addr + chunk_size))) {
+ found = B_TRUE;
+ /*
+ * check if this is the last buffer in the block
+ * If so, then reset the hint for the size;
+ */
+
+ if ((pktbuf_pp + bufsize) >= (dvma_addr + chunk_size))
+ ring_info->hint[pktbufsz_type] = NO_HINT;
+ }
+ }
+
+ if (found == B_FALSE) {
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (!found)"
+ "buf_pp $%p btype %d anchor_index %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index));
+
+ /*
+ * This is the first buffer of the block of this
+ * size. Need to search the whole information
+ * array.
+ * the search algorithm uses a binary tree search
+ * algorithm. It assumes that the information is
+ * already sorted with increasing order
+ * info[0] < info[1] < info[2] .... < info[n-1]
+ * where n is the size of the information array
+ */
+ r_index = rbr_p->num_blocks - 1;
+ l_index = 0;
+ search_done = B_FALSE;
+ anchor_index = MID_INDEX(r_index, l_index);
+ while (search_done == B_FALSE) {
+ if ((r_index == l_index) ||
+ (iteration >= max_iterations))
+ search_done = B_TRUE;
+ end_side = TO_RIGHT; /* to the right */
+ base_side = TO_LEFT; /* to the left */
+ /* read the DVMA address information and sort it */
+ dvma_addr = bufinfo[anchor_index].dvma_addr;
+ chunk_size = bufinfo[anchor_index].buf_size;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (searching)"
+ "buf_pp $%p btype %d "
+ "anchor_index %d chunk_size %d dvmaaddr $%p",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index,
+ chunk_size,
+ dvma_addr));
+
+ if (pktbuf_pp >= dvma_addr)
+ base_side = TO_RIGHT; /* to the right */
+ if (pktbuf_pp < (dvma_addr + chunk_size))
+ end_side = TO_LEFT; /* to the left */
+
+ switch (base_side + end_side) {
+ case IN_MIDDLE:
+ /* found */
+ found = B_TRUE;
+ search_done = B_TRUE;
+ if ((pktbuf_pp + bufsize) <
+ (dvma_addr + chunk_size))
+ ring_info->hint[pktbufsz_type] =
+ bufinfo[anchor_index].buf_index;
+ break;
+ case BOTH_RIGHT:
+ /* not found: go to the right */
+ l_index = anchor_index + 1;
+ anchor_index =
+ MID_INDEX(r_index, l_index);
+ break;
+
+ case BOTH_LEFT:
+ /* not found: go to the left */
+ r_index = anchor_index - 1;
+ anchor_index = MID_INDEX(r_index,
+ l_index);
+ break;
+ default: /* should not come here */
+ return (NXGE_ERROR);
+ }
+ iteration++;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (search done)"
+ "buf_pp $%p btype %d anchor_index %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index));
+ }
+
+ if (found == B_FALSE) {
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (search failed)"
+ "buf_pp $%p btype %d anchor_index %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ anchor_index));
+ return (NXGE_ERROR);
+ }
+
+found_index:
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (FOUND1)"
+ "buf_pp $%p btype %d bufsize %d anchor_index %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ bufsize,
+ anchor_index));
+
+ /* index of the first block in this chunk */
+ chunk_index = bufinfo[anchor_index].start_index;
+ dvma_addr = bufinfo[anchor_index].dvma_addr;
+ page_size_mask = ring_info->block_size_mask;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (FOUND3), get chunk)"
+ "buf_pp $%p btype %d bufsize %d "
+ "anchor_index %d chunk_index %d dvma $%p",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ bufsize,
+ anchor_index,
+ chunk_index,
+ dvma_addr));
+
+ offset = pktbuf_pp - dvma_addr; /* offset within the chunk */
+ block_size = rbr_p->block_size; /* System block(page) size */
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: (FOUND4), get chunk)"
+ "buf_pp $%p btype %d bufsize %d "
+ "anchor_index %d chunk_index %d dvma $%p "
+ "offset %d block_size %d",
+ pkt_buf_addr_pp,
+ pktbufsz_type,
+ bufsize,
+ anchor_index,
+ chunk_index,
+ dvma_addr,
+ offset,
+ block_size));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "==> getting total index"));
+
+ block_index = (offset / block_size); /* index within chunk */
+ total_index = chunk_index + block_index;
+
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: "
+ "total_index %d dvma_addr $%p "
+ "offset %d block_size %d "
+ "block_index %d ",
+ total_index, dvma_addr,
+ offset, block_size,
+ block_index));
+
+ *pkt_buf_addr_p = (uint64_t *)((uint64_t)bufinfo[anchor_index].kaddr
+ + offset);
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: "
+ "total_index %d dvma_addr $%p "
+ "offset %d block_size %d "
+ "block_index %d "
+ "*pkt_buf_addr_p $%p",
+ total_index, dvma_addr,
+ offset, block_size,
+ block_index,
+ *pkt_buf_addr_p));
+
+
+ *msg_index = total_index;
+ *bufoffset = (offset & page_size_mask);
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_rxbuf_pp_to_vp: get msg index: "
+ "msg_index %d bufoffset_index %d",
+ *msg_index,
+ *bufoffset));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "<== nxge_rxbuf_pp_to_vp"));
+
+ return (NXGE_OK);
+}
+
+
+/*
+ * used by quick sort (qsort) function
+ * to perform comparison
+ */
+static int
+nxge_sort_compare(const void *p1, const void *p2)
+{
+
+ rxbuf_index_info_t *a, *b;
+
+ a = (rxbuf_index_info_t *)p1;
+ b = (rxbuf_index_info_t *)p2;
+
+ if (a->dvma_addr > b->dvma_addr)
+ return (1);
+ if (a->dvma_addr < b->dvma_addr)
+ return (-1);
+ return (0);
+}
+
+
+
+/*
+ * grabbed this sort implementation from common/syscall/avl.c
+ *
+ */
+/*
+ * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
+ * v = Ptr to array/vector of objs
+ * n = # objs in the array
+ * s = size of each obj (must be multiples of a word size)
+ * f = ptr to function to compare two objs
+ * returns (-1 = less than, 0 = equal, 1 = greater than
+ */
+void
+nxge_ksort(caddr_t v, int n, int s, int (*f)())
+{
+ int g, i, j, ii;
+ unsigned int *p1, *p2;
+ unsigned int tmp;
+
+ /* No work to do */
+ if (v == NULL || n <= 1)
+ return;
+ /* Sanity check on arguments */
+ ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0);
+ ASSERT(s > 0);
+
+ for (g = n / 2; g > 0; g /= 2) {
+ for (i = g; i < n; i++) {
+ for (j = i - g; j >= 0 &&
+ (*f)(v + j * s, v + (j + g) * s) == 1;
+ j -= g) {
+ p1 = (unsigned *)(v + j * s);
+ p2 = (unsigned *)(v + (j + g) * s);
+ for (ii = 0; ii < s / 4; ii++) {
+ tmp = *p1;
+ *p1++ = *p2;
+ *p2++ = tmp;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * Initialize data structures required for rxdma
+ * buffer dvma->vmem address lookup
+ */
+/*ARGSUSED*/
+static nxge_status_t
+nxge_rxbuf_index_info_init(p_nxge_t nxgep, p_rx_rbr_ring_t rbrp)
+{
+
+ int index;
+ rxring_info_t *ring_info;
+ int max_iteration = 0, max_index = 0;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_rxbuf_index_info_init"));
+
+ ring_info = rbrp->ring_info;
+ ring_info->hint[0] = NO_HINT;
+ ring_info->hint[1] = NO_HINT;
+ ring_info->hint[2] = NO_HINT;
+ max_index = rbrp->num_blocks;
+
+ /* read the DVMA address information and sort it */
+ /* do init of the information array */
+
+
+ NXGE_DEBUG_MSG((nxgep, DMA2_CTL,
+ " nxge_rxbuf_index_info_init Sort ptrs"));
+
+ /* sort the array */
+ nxge_ksort((void *)ring_info->buffer, max_index,
+ sizeof (rxbuf_index_info_t), nxge_sort_compare);
+
+
+
+ for (index = 0; index < max_index; index++) {
+ NXGE_DEBUG_MSG((nxgep, DMA2_CTL,
+ " nxge_rxbuf_index_info_init: sorted chunk %d "
+ " ioaddr $%p kaddr $%p size %x",
+ index, ring_info->buffer[index].dvma_addr,
+ ring_info->buffer[index].kaddr,
+ ring_info->buffer[index].buf_size));
+ }
+
+ max_iteration = 0;
+ while (max_index >= (1ULL << max_iteration))
+ max_iteration++;
+ ring_info->max_iterations = max_iteration + 1;
+ NXGE_DEBUG_MSG((nxgep, DMA2_CTL,
+ " nxge_rxbuf_index_info_init Find max iter %d",
+ ring_info->max_iterations));
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_rxbuf_index_info_init"));
+ return (NXGE_OK);
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_rx_parse_header(p_nxge_t nxgep, uint64_t *pkt_buf_addr_p,
+ uint16_t hdr_size)
+{
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_parse_header"));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_parse_header: "
+ "buffer $%p headr_size %d",
+ pkt_buf_addr_p, hdr_size));
+
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rx_parse_header"));
+ return (NXGE_OK);
+
+}
+
+/*ARGSUSED*/
+void
+nxge_dump_rcr_entry(p_nxge_t nxgep, p_rcr_entry_t entry_p)
+{
+#ifdef NXGE_DEBUG
+
+ uint32_t bptr;
+ uint64_t pp;
+
+ bptr = entry_p->bits.hdw.pkt_buf_addr;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "\trcr entry $%p "
+ "\trcr entry 0x%0llx "
+ "\trcr entry 0x%08x "
+ "\trcr entry 0x%08x "
+ "\tvalue 0x%0llx\n"
+ "\tmulti = %d\n"
+ "\tpkt_type = 0x%x\n"
+ "\tzero_copy = %d\n"
+ "\tnoport = %d\n"
+ "\tpromis = %d\n"
+ "\terror = 0x%04x\n"
+ "\tdcf_err = 0x%01x\n"
+ "\tl2_len = %d\n"
+ "\tpktbufsize = %d\n"
+ "\tpkt_buf_addr = $%p\n"
+ "\tpkt_buf_addr (<< 6) = $%p\n",
+ entry_p,
+ *(int64_t *)entry_p,
+ *(int32_t *)entry_p,
+ *(int32_t *)((char *)entry_p + 32),
+ entry_p->value,
+ entry_p->bits.hdw.multi,
+ entry_p->bits.hdw.pkt_type,
+ entry_p->bits.hdw.zero_copy,
+ entry_p->bits.hdw.noport,
+ entry_p->bits.hdw.promis,
+ entry_p->bits.hdw.error,
+ entry_p->bits.hdw.dcf_err,
+ entry_p->bits.hdw.l2_len,
+ entry_p->bits.hdw.pktbufsz,
+ bptr,
+ entry_p->bits.ldw.pkt_buf_addr));
+
+ pp = (entry_p->value & RCR_PKT_BUF_ADDR_MASK) <<
+ RCR_PKT_BUF_ADDR_SHIFT;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "rcr pp 0x%llx l2 len %d",
+ pp, (*(int64_t *)entry_p >> 40) & 0x3fff));
+#endif
+}
+
+void
+nxge_rxdma_regs_dump(p_nxge_t nxgep, int rdc)
+{
+ npi_handle_t handle;
+ rbr_stat_t rbr_stat;
+ addr44_t hd_addr;
+ addr44_t tail_addr;
+ uint16_t qlen;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_regs_dump: rdc channel %d", rdc));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ /* RBR head */
+ hd_addr.addr = 0;
+ (void) npi_rxdma_rdc_rbr_head_get(handle, rdc, &hd_addr);
+ printf("nxge_rxdma_regs_dump: got hdptr $%p \n",
+ (void *)hd_addr.addr);
+
+ /* RBR stats */
+ (void) npi_rxdma_rdc_rbr_stat_get(handle, rdc, &rbr_stat);
+ printf("nxge_rxdma_regs_dump: rbr len %d \n", rbr_stat.bits.ldw.qlen);
+
+ /* RCR tail */
+ tail_addr.addr = 0;
+ (void) npi_rxdma_rdc_rcr_tail_get(handle, rdc, &tail_addr);
+ printf("nxge_rxdma_regs_dump: got tail ptr $%p \n",
+ (void *)tail_addr.addr);
+
+ /* RCR qlen */
+ (void) npi_rxdma_rdc_rcr_qlen_get(handle, rdc, &qlen);
+ printf("nxge_rxdma_regs_dump: rcr len %x \n", qlen);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_regs_dump: rdc rdc %d", rdc));
+}
+
+
+/*ARGSUSED*/
+void
+nxge_rxdma_stop(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_stop"));
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_rx_mac_disable(nxgep);
+ (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_stop"));
+}
+
+void
+nxge_rxdma_stop_reinit(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_stop_reinit"));
+
+ (void) nxge_rxdma_stop(nxgep);
+ (void) nxge_uninit_rxdma_channels(nxgep);
+ (void) nxge_init_rxdma_channels(nxgep);
+
+#ifndef AXIS_DEBUG_LB
+ (void) nxge_xcvr_init(nxgep);
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
+#endif
+ (void) nxge_rx_mac_enable(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_stop_reinit"));
+}
+
+nxge_status_t
+nxge_rxdma_hw_mode(p_nxge_t nxgep, boolean_t enable)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_mode: mode %d", enable));
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_mode: not initialized"));
+ return (NXGE_ERROR);
+ }
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ if (rx_rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_mode: NULL ring pointer"));
+ return (NXGE_ERROR);
+ }
+ if (rx_rbr_rings->rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_mode: NULL rbr rings pointer"));
+ return (NXGE_ERROR);
+ }
+
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_mode: no channel"));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_mode (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ for (i = 0; i < ndmas; i++) {
+ if (rbr_rings == NULL || rbr_rings[i] == NULL) {
+ continue;
+ }
+ channel = rbr_rings[i]->rdc;
+ if (enable) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_mode: channel %d (enable)",
+ channel));
+ rs = npi_rxdma_cfg_rdc_enable(handle, channel);
+ } else {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_mode: channel %d (disable)",
+ channel));
+ rs = npi_rxdma_cfg_rdc_disable(handle, channel);
+ }
+ }
+
+ status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_rxdma_hw_mode: status 0x%x", status));
+
+ return (status);
+}
+
+void
+nxge_rxdma_enable_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_rxdma_enable_channel: channel %d", channel));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_rxdma_cfg_rdc_enable(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_rxdma_enable_channel"));
+}
+
+
+void
+nxge_rxdma_disable_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_rxdma_disable_channel: channel %d", channel));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_rxdma_cfg_rdc_disable(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_rxdma_disable_channel"));
+}
+
+void
+nxge_hw_start_rx(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_start_rx"));
+
+ (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START);
+ (void) nxge_rx_mac_enable(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_start_rx"));
+}
+
+/*ARGSUSED*/
+void
+nxge_fixup_rxdma_rings(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t rdc;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_fixup_rxdma_rings"));
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ if (rx_rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_fixup_rxdma_rings: NULL ring pointer"));
+ return;
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_fixup_rxdma_rings: no channel"));
+ return;
+ }
+
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ if (rx_rcr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_fixup_rxdma_rings: NULL ring pointer"));
+ return;
+ }
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_fixup_rxdma_rings (ndmas %d)", ndmas));
+
+ nxge_rxdma_hw_stop(nxgep);
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ for (i = 0; i < ndmas; i++) {
+ rdc = rbr_rings[i]->rdc;
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_fixup_rxdma_rings: channel %d "
+ "ring $%px", rdc, rbr_rings[i]));
+ (void) nxge_rxdma_fixup_channel(nxgep, rdc, i);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_fixup_rxdma_rings"));
+}
+
+void
+nxge_rxdma_fix_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_fix_channel"));
+ i = nxge_rxdma_get_ring_index(nxgep, channel);
+ if (i < 0) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_fix_channel: no entry found"));
+ return;
+ }
+
+ nxge_rxdma_fixup_channel(nxgep, channel, i);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_txdma_fix_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_rxdma_fixup_channel(p_nxge_t nxgep, uint16_t channel, int entry)
+{
+ int ndmas;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_mbox_areas_t rx_mbox_areas_p;
+ p_rx_mbox_t *rx_mbox_p;
+ p_nxge_dma_pool_t dma_buf_poolp;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_rx_rbr_ring_t rbrp;
+ p_rx_rcr_ring_t rcrp;
+ p_rx_mbox_t mboxp;
+ p_nxge_dma_common_t dmap;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_fixup_channel"));
+
+ (void) nxge_rxdma_stop_channel(nxgep, channel);
+
+ dma_buf_poolp = nxgep->rx_buf_pool_p;
+ dma_cntl_poolp = nxgep->rx_cntl_pool_p;
+
+ if (!dma_buf_poolp->buf_allocated || !dma_cntl_poolp->buf_allocated) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_rxdma_fixup_channel: buf not allocated"));
+ return;
+ }
+
+ ndmas = dma_buf_poolp->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_rxdma_fixup_channel: no dma allocated"));
+ return;
+ }
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ rx_mbox_areas_p = nxgep->rx_mbox_areas_p;
+ rx_mbox_p = rx_mbox_areas_p->rxmbox_areas;
+
+ /* Reinitialize the receive block and completion rings */
+ rbrp = (p_rx_rbr_ring_t)rbr_rings[entry],
+ rcrp = (p_rx_rcr_ring_t)rcr_rings[entry],
+ mboxp = (p_rx_mbox_t)rx_mbox_p[entry];
+
+
+ rbrp->rbr_wr_index = (rbrp->rbb_max - 1);
+ rbrp->rbr_rd_index = 0;
+ rcrp->comp_rd_index = 0;
+ rcrp->comp_wt_index = 0;
+
+ dmap = (p_nxge_dma_common_t)&rcrp->rcr_desc;
+ bzero((caddr_t)dmap->kaddrp, dmap->alength);
+
+ status = nxge_rxdma_start_channel(nxgep, channel,
+ rbrp, rcrp, mboxp);
+ if (status != NXGE_OK) {
+ goto nxge_rxdma_fixup_channel_fail;
+ }
+ if (status != NXGE_OK) {
+ goto nxge_rxdma_fixup_channel_fail;
+ }
+
+nxge_rxdma_fixup_channel_fail:
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_fixup_channel: failed (0x%08x)", status));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_fixup_channel"));
+}
+
+int
+nxge_rxdma_get_ring_index(p_nxge_t nxgep, uint16_t channel)
+{
+ int i, ndmas;
+ uint16_t rdc;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_ring_index: channel %d", channel));
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ if (rx_rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_ring_index: NULL ring pointer"));
+ return (-1);
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_ring_index: no channel"));
+ return (-1);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_ring_index (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ for (i = 0; i < ndmas; i++) {
+ rdc = rbr_rings[i]->rdc;
+ if (channel == rdc) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rbr_ring: "
+ "channel %d (index %d) "
+ "ring %d", channel, i,
+ rbr_rings[i]));
+ return (i);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rbr_ring_index: not found"));
+
+ return (-1);
+}
+
+p_rx_rbr_ring_t
+nxge_rxdma_get_rbr_ring(p_nxge_t nxgep, uint16_t channel)
+{
+ int i, ndmas;
+ uint16_t rdc;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rbr_ring: channel %d", channel));
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ if (rx_rbr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rbr_ring: NULL ring pointer"));
+ return (NULL);
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rbr_ring: no channel"));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_ring (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ for (i = 0; i < ndmas; i++) {
+ rdc = rbr_rings[i]->rdc;
+ if (channel == rdc) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rbr_ring: channel %d "
+ "ring $%p", channel, rbr_rings[i]));
+ return (rbr_rings[i]);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rbr_ring: not found"));
+
+ return (NULL);
+}
+
+p_rx_rcr_ring_t
+nxge_rxdma_get_rcr_ring(p_nxge_t nxgep, uint16_t channel)
+{
+ int i, ndmas;
+ uint16_t rdc;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rcr_ring: channel %d", channel));
+
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ if (rx_rcr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rcr_ring: NULL ring pointer"));
+ return (NULL);
+ }
+ ndmas = rx_rcr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rcr_ring: no channel"));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rcr_ring (ndmas %d)", ndmas));
+
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ for (i = 0; i < ndmas; i++) {
+ rdc = rcr_rings[i]->rdc;
+ if (channel == rdc) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_get_rcr_ring: channel %d "
+ "ring $%p", channel, rcr_rings[i]));
+ return (rcr_rings[i]);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_get_rcr_ring: not found"));
+
+ return (NULL);
+}
+
+/*
+ * Static functions start here.
+ */
+static p_rx_msg_t
+nxge_allocb(size_t size, uint32_t pri, p_nxge_dma_common_t dmabuf_p)
+{
+ p_rx_msg_t nxge_mp = NULL;
+ p_nxge_dma_common_t dmamsg_p;
+ uchar_t *buffer;
+
+ nxge_mp = KMEM_ZALLOC(sizeof (rx_msg_t), KM_NOSLEEP);
+ if (nxge_mp == NULL) {
+ NXGE_DEBUG_MSG((NULL, MEM_CTL,
+ "Allocation of a rx msg failed."));
+ goto nxge_allocb_exit;
+ }
+
+ nxge_mp->use_buf_pool = B_FALSE;
+ if (dmabuf_p) {
+ nxge_mp->use_buf_pool = B_TRUE;
+ dmamsg_p = (p_nxge_dma_common_t)&nxge_mp->buf_dma;
+ *dmamsg_p = *dmabuf_p;
+ dmamsg_p->nblocks = 1;
+ dmamsg_p->block_size = size;
+ dmamsg_p->alength = size;
+ buffer = (uchar_t *)dmabuf_p->kaddrp;
+
+ dmabuf_p->kaddrp = (void *)
+ ((char *)dmabuf_p->kaddrp + size);
+ dmabuf_p->ioaddr_pp = (void *)
+ ((char *)dmabuf_p->ioaddr_pp + size);
+ dmabuf_p->alength -= size;
+ dmabuf_p->offset += size;
+ dmabuf_p->dma_cookie.dmac_laddress += size;
+ dmabuf_p->dma_cookie.dmac_size -= size;
+
+ } else {
+ buffer = KMEM_ALLOC(size, KM_NOSLEEP);
+ if (buffer == NULL) {
+ NXGE_DEBUG_MSG((NULL, MEM_CTL,
+ "Allocation of a receive page failed."));
+ goto nxge_allocb_fail1;
+ }
+ }
+
+ nxge_mp->rx_mblk_p = desballoc(buffer, size, pri, &nxge_mp->freeb);
+ if (nxge_mp->rx_mblk_p == NULL) {
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "desballoc failed."));
+ goto nxge_allocb_fail2;
+ }
+
+ nxge_mp->buffer = buffer;
+ nxge_mp->block_size = size;
+ nxge_mp->freeb.free_func = (void (*)())nxge_freeb;
+ nxge_mp->freeb.free_arg = (caddr_t)nxge_mp;
+ nxge_mp->ref_cnt = 1;
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ nxge_mp->pass_up_cnt = nxge_mp->ref_cnt;
+ nxge_mp->release = B_FALSE;
+#endif
+ nxge_mp->free = B_TRUE;
+ nxge_mp->rx_use_bcopy = B_FALSE;
+
+ atomic_add_32(&nxge_mblks_pending, 1);
+
+ goto nxge_allocb_exit;
+
+nxge_allocb_fail2:
+ if (!nxge_mp->use_buf_pool) {
+ KMEM_FREE(buffer, size);
+ }
+
+nxge_allocb_fail1:
+ KMEM_FREE(nxge_mp, sizeof (rx_msg_t));
+ nxge_mp = NULL;
+
+nxge_allocb_exit:
+ return (nxge_mp);
+}
+
+#ifdef RX_USE_BCOPY
+p_mblk_t
+nxge_dupb(p_rx_msg_t nxge_mp, uint_t offset, size_t size)
+{
+ p_mblk_t mp;
+
+
+ mp = allocb(size + 4, nxge_mp->pri);
+
+ if (mp == NULL) {
+ NXGE_DEBUG_MSG((NULL, RX_CTL, "desballoc failed"));
+ goto nxge_dupb_cexit;
+ }
+ mp->b_rptr += 2;
+ bcopy((void *)&nxge_mp->buffer[offset], mp->b_rptr, size);
+ mp->b_wptr = mp->b_rptr + size;
+
+nxge_dupb_cexit:
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "<== nxge_dupb mp = $%p",
+ nxge_mp));
+ return (mp);
+}
+
+#else
+p_mblk_t
+nxge_dupb(p_rx_msg_t nxge_mp, uint_t offset, size_t size)
+{
+ p_mblk_t mp;
+
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "==> nxge_dupb"));
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "nxge_mp = $%p "
+ "offset = 0x%08X "
+ "size = 0x%08X",
+ nxge_mp, offset, size));
+
+ mp = desballoc(&nxge_mp->buffer[offset], size,
+ 0, &nxge_mp->freeb);
+ if (mp == NULL) {
+ NXGE_DEBUG_MSG((NULL, RX_CTL, "desballoc failed"));
+ goto nxge_dupb_exit;
+ }
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ atomic_inc_32(&nxge_mp->pass_up_cnt);
+#else
+ atomic_inc_32(&nxge_mp->ref_cnt);
+#endif
+
+
+nxge_dupb_exit:
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "<== nxge_dupb mp = $%p",
+ nxge_mp));
+ return (mp);
+}
+
+p_mblk_t
+nxge_dupb_bcopy(p_rx_msg_t nxge_mp, uint_t offset, size_t size)
+{
+ p_mblk_t mp;
+ uchar_t *dp;
+
+ mp = allocb(size + NXGE_RXBUF_EXTRA, 0);
+ if (mp == NULL) {
+ NXGE_DEBUG_MSG((NULL, RX_CTL, "desballoc failed"));
+ goto nxge_dupb_bcopy_exit;
+ }
+ dp = mp->b_rptr = mp->b_rptr + NXGE_RXBUF_EXTRA;
+ bcopy((void *)&nxge_mp->buffer[offset], dp, size);
+ mp->b_wptr = dp + size;
+
+nxge_dupb_bcopy_exit:
+ NXGE_DEBUG_MSG((NULL, MEM_CTL, "<== nxge_dupb mp = $%p",
+ nxge_mp));
+ return (mp);
+}
+
+#endif
+
+void nxge_post_page(p_nxge_t nxgep, p_rx_rbr_ring_t rx_rbr_p,
+ p_rx_msg_t rx_msg_p);
+
+void
+nxge_post_page(p_nxge_t nxgep, p_rx_rbr_ring_t rx_rbr_p, p_rx_msg_t rx_msg_p)
+{
+
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_post_page"));
+
+ /* Reuse this buffer */
+ rx_msg_p->free = B_FALSE;
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0;
+ rx_msg_p->pkt_buf_size = 0;
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ rx_msg_p->pass_up_cnt = 1;
+ rx_msg_p->ref_cnt = 1;
+#endif
+
+ if (rx_rbr_p->rbr_use_bcopy) {
+ rx_msg_p->rx_use_bcopy = B_FALSE;
+ atomic_dec_32(&rx_rbr_p->rbr_consumed);
+ }
+
+ /*
+ * Get the rbr header pointer and its offset index.
+ */
+ MUTEX_ENTER(&rx_rbr_p->post_lock);
+
+
+ rx_rbr_p->rbr_wr_index = ((rx_rbr_p->rbr_wr_index + 1) &
+ rx_rbr_p->rbr_wrap_mask);
+ rx_rbr_p->rbr_desc_vp[rx_rbr_p->rbr_wr_index] = rx_msg_p->shifted_addr;
+ MUTEX_EXIT(&rx_rbr_p->post_lock);
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ npi_rxdma_rdc_rbr_kick(handle, rx_rbr_p->rdc, 1);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_post_page (channel %d post_next_index %d)",
+ rx_rbr_p->rdc, rx_rbr_p->rbr_wr_index));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_post_page"));
+}
+
+#if defined(RX_USE_RECLAIM_POST)
+void
+nxge_rx_reclaim_post_page(p_nxge_t nxgep, p_rx_rbr_ring_t rx_rbr_p)
+{
+
+ npi_handle_t handle;
+ uint8_t channel;
+ int post_count;
+ uint32_t *tail_vp;
+ uint32_t bkaddr;
+ uint32_t next_index;
+ addr44_t tail_addr_pp;
+ npi_status_t rs = NPI_SUCCESS;
+ p_rx_rcr_ring_t rcr_p;
+ p_rx_msg_t *rx_msg_ring_p;
+ p_rx_msg_t rx_msg_p;
+ int buffers_checked;
+ int msg_index;
+ int rbr_msg_count;
+ int rbr_wr_index;
+ int free_count;
+
+ if (!rx_rbr_p->hw_freed)
+ return;
+
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ MUTEX_ENTER(&rx_rbr_p->post_lock);
+ channel = rx_rbr_p->rdc;
+ rx_msg_ring_p = rx_rbr_p->rx_msg_ring;
+
+ rbr_wr_index = rx_rbr_p->rbr_wr_index;
+ free_count = rx_rbr_p->hw_freed;
+ post_count = 0;
+ buffers_checked = 0;
+ msg_index = rx_rbr_p->msg_rd_index;
+ rbr_msg_count = rx_rbr_p->msg_cnt;
+ NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rx_reclaim_post_page (channel %d wr_index %x"
+ " free 0x%x msg_index 0x%x", rx_rbr_p->rdc,
+ rbr_wr_index, free_count, msg_index));
+
+ while ((post_count < free_count) &&
+ (buffers_checked < rbr_msg_count)) {
+ rx_msg_p = rx_msg_ring_p[msg_index];
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ if ((rx_msg_p->ref_cnt == rx_msg_p->pass_up_cnt) &&
+ (rx_msg_p->free == B_TRUE)) {
+#else
+ if ((rx_msg_p->ref_cnt == 1) && (rx_msg_p->free == B_TRUE)) {
+#endif
+ /* Reuse this buffer */
+ rx_msg_p->free = B_FALSE;
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0;
+ rx_msg_p->pkt_buf_size = 0;
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ rx_msg_p->pass_up_cnt = 1;
+ rx_msg_p->ref_cnt = 1;
+#endif
+ rbr_wr_index = ((rbr_wr_index + 1) %
+ rx_rbr_p->rbb_max);
+ rx_rbr_p->rbr_desc_vp[rbr_wr_index] =
+ rx_msg_p->shifted_addr;
+
+ post_count++;
+ }
+ buffers_checked++;
+ msg_index = (msg_index + 1) % rbr_msg_count;
+ }
+
+ if (post_count > 0) {
+ npi_rxdma_rdc_rbr_kick(handle, channel, post_count);
+ }
+
+ rx_rbr_p->rbr_wr_index = rbr_wr_index;
+ rx_rbr_p->msg_rd_index = msg_index;
+ atomic_add_32(&rx_rbr_p->hw_freed, (0 - post_count));
+ MUTEX_EXIT(&rx_rbr_p->post_lock);
+
+ NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "nxge_rx_reclaim_post_page "
+ " (channel %d wr_index %x free 0x%x msg_index 0x%x posted %x",
+ rx_rbr_p->rdc, rbr_wr_index,
+ rx_rbr_p->hw_freed, msg_index, post_count));
+
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_post_page"));
+}
+#endif
+
+
+
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+
+void
+nxge_freeb(p_rx_msg_t rx_msg_p)
+{
+ size_t size;
+ uchar_t *buffer = NULL;
+ int ref_cnt;
+
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL, "==> nxge_freeb"));
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL,
+ "nxge_freeb:rx_msg_p = $%p (block pending %d)",
+ rx_msg_p, nxge_mblks_pending));
+
+ ref_cnt = atomic_inc_32_nv(&rx_msg_p->ref_cnt);
+
+ /*
+ * Repost buffer.
+ */
+ if ((ref_cnt == rx_msg_p->pass_up_cnt) && (rx_msg_p->free == B_TRUE)) {
+ if (rx_msg_p->release == B_TRUE) {
+ buffer = rx_msg_p->buffer;
+ size = rx_msg_p->block_size;
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL,
+ "nxge_freeb: will free:"
+ " rx_msg_p = $%p (block pending %d)",
+ (long long)rx_msg_p, nxge_mblks_pending));
+
+ KMEM_FREE(rx_msg_p, sizeof (rx_msg_t));
+ if (!rx_msg_p->use_buf_pool) {
+ KMEM_FREE(buffer, size);
+ }
+ return;
+ }
+#if !defined(RX_USE_RECLAIM_POST)
+ NXGE_DEBUG_MSG((NULL, RX_CTL,
+ "nxge_freeb: post page $%p:", rx_msg_p));
+ nxge_post_page(rx_msg_p->nxgep, rx_msg_p->rx_rbr_p,
+ rx_msg_p);
+#endif
+ }
+
+
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL, "<== nxge_freeb"));
+}
+
+#else
+
+void
+nxge_freeb(p_rx_msg_t rx_msg_p)
+{
+ size_t size;
+ uchar_t *buffer = NULL;
+ int ref_cnt;
+
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL, "==> nxge_freeb"));
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL,
+ "nxge_freeb:rx_msg_p = $%p (block pending %d)",
+ rx_msg_p, nxge_mblks_pending));
+
+ ref_cnt = atomic_add_32_nv(&rx_msg_p->ref_cnt, -1);
+ if (!ref_cnt) {
+ buffer = rx_msg_p->buffer;
+ size = rx_msg_p->block_size;
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL, "nxge_freeb: "
+ "will free: rx_msg_p = $%p (block pending %d)",
+ (long long)rx_msg_p, nxge_mblks_pending));
+
+ KMEM_FREE(rx_msg_p, sizeof (rx_msg_t));
+ if (!rx_msg_p->use_buf_pool) {
+ KMEM_FREE(buffer, size);
+ }
+ }
+
+#if !defined(RX_USE_RECLAIM_POST)
+ /*
+ * Repost buffer.
+ */
+ if ((ref_cnt == 1) && (rx_msg_p->free == B_TRUE)) {
+ NXGE_DEBUG_MSG((NULL, RX_CTL,
+ "nxge_freeb: post page $%p:", rx_msg_p));
+ nxge_post_page(rx_msg_p->nxgep, rx_msg_p->rx_rbr_p,
+ rx_msg_p);
+ }
+#endif
+
+ NXGE_DEBUG_MSG((NULL, MEM2_CTL, "<== nxge_freeb"));
+}
+
+
+#endif
+/*ARGSUSED*/
+boolean_t
+nxge_replace_page(p_nxge_t nxgep)
+{
+ boolean_t status = B_TRUE;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_replace_page"));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_replace_page"));
+ return (status);
+}
+
+uint_t
+nxge_rx_intr(void *arg1, void *arg2)
+{
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+ p_nxge_ldg_t ldgp;
+ uint8_t channel;
+ npi_handle_t handle;
+ rx_dma_ctl_stat_t cs;
+
+#ifdef NXGE_DEBUG
+ rxdma_cfig1_t cfg;
+#endif
+#ifndef RDC_NPI_DIRECT
+ npi_status_t rs = NPI_SUCCESS;
+#endif
+ uint_t serviced = DDI_INTR_UNCLAIMED;
+
+ if (ldvp == NULL) {
+ NXGE_DEBUG_MSG((NULL, INT_CTL,
+ "<== nxge_rx_intr: arg2 $%p arg1 $%p",
+ nxgep, ldvp));
+
+ return (DDI_INTR_CLAIMED);
+ }
+
+ if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
+ nxgep = ldvp->nxgep;
+ }
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_intr: arg2 $%p arg1 $%p",
+ nxgep, ldvp));
+
+ /*
+ * This interrupt handler is for a specific
+ * receive dma channel.
+ */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Get the control and status for this channel.
+ */
+ channel = ldvp->channel;
+ ldgp = ldvp->ldgp;
+#ifdef RDC_NPI_DIRECT
+ RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value);
+#else
+ rs = npi_rxdma_control_status(handle, OP_GET, channel, &cs);
+ if (rs != NPI_SUCCESS) {
+ serviced = DDI_INTR_CLAIMED;
+ goto nxge_intr_exit;
+ }
+
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_intr:channel %d "
+ "cs 0x%016llx rcrto 0x%x rcrthres %x",
+ channel,
+ cs.value,
+ cs.bits.hdw.rcrto,
+ cs.bits.hdw.rcrthres));
+
+
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+ nxge_rx_pkts_vring(nxgep, ldvp->vdma_index, ldvp, cs);
+#else
+ nxge_rx_pkts_vring(nxgep, ldvp->vdma_index, ldvp);
+#endif
+ serviced = DDI_INTR_CLAIMED;
+
+ /* error events. */
+ if (cs.value & RX_DMA_CTL_STAT_ERROR) {
+ (void) nxge_rx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs);
+ }
+
+nxge_intr_exit:
+
+
+ /*
+ * Enable the mailbox update interrupt if we want
+ * to use mailbox. We probably don't need to use
+ * mailbox as it only saves us one pio read.
+ * Also write 1 to rcrthres and rcrto to clear
+ * these two edge triggered bits.
+ */
+
+ cs.value &= RX_DMA_CTL_STAT_WR1C;
+ cs.bits.hdw.mex = 1;
+#ifdef RDC_NPI_DIRECT
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel,
+ cs.value);
+#else
+ (void) npi_rxdma_control_status(handle, OP_SET,
+ channel, &cs);
+#endif
+
+
+ /*
+ * Rearm this logical group if this is a single device
+ * group.
+ */
+ if (ldgp->nldvs == 1) {
+#ifdef RDC_NPI_DIRECT
+ ldgimgm_t mgm;
+ mgm.value = 0;
+ mgm.bits.ldw.arm = 1;
+ mgm.bits.ldw.timer = ldgp->ldg_timer;
+ NXGE_REG_WR64(handle,
+ LDGIMGN_REG + LDSV_OFFSET(ldgp->ldg),
+ mgm.value);
+#else
+ (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ B_TRUE, ldgp->ldg_timer);
+#endif
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rx_intr: serviced %d",
+ serviced));
+ return (serviced);
+}
+
+/*
+ * Process the packets received in the specified logical device
+ * and pass up a chain of message blocks to the upper layer.
+ */
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+static void
+nxge_rx_pkts_vring(p_nxge_t nxgep, uint_t vindex, p_nxge_ldv_t ldvp,
+#else
+static void
+nxge_rx_pkts_vring(p_nxge_t nxgep, uint_t vindex, p_nxge_ldv_t ldvp)
+#endif
+{
+ p_mblk_t mp;
+ p_rx_rcr_ring_t rcrp;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts_vring"));
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+ if ((mp = nxge_rx_pkts(nxgep, vindex, ldvp, &rcrp, cs)) == NULL) {
+#else
+ if ((mp = nxge_rx_pkts(nxgep, vindex, ldvp, &rcrp)) == NULL) {
+#endif
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rx_pkts_vring: no mp"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts_vring: $%p",
+ mp));
+
+#ifdef NXGE_DEBUG
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts_vring:calling mac_rx "
+ "LEN %d mp $%p mp->b_next $%p rcrp $%p "
+ "mac_handle $%p",
+ (mp->b_wptr - mp->b_rptr),
+ mp, mp->b_next,
+ rcrp, rcrp->rcr_mac_handle));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts_vring: dump packets "
+ "(mp $%p b_rptr $%p b_wptr $%p):\n %s",
+ mp,
+ mp->b_rptr,
+ mp->b_wptr,
+ nxge_dump_packet((char *)mp->b_rptr, 64)));
+
+ if (mp->b_next) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts_vring: dump next packets "
+ "(b_rptr $%p): %s",
+ mp->b_next->b_rptr,
+ nxge_dump_packet((char *)mp->b_next->b_rptr,
+ 64)));
+
+ }
+#endif
+
+ mac_rx(nxgep->mach, rcrp->rcr_mac_handle, mp);
+
+#if defined(RX_USE_RECLAIM_POST)
+ if (rcrp->rx_rbr_p->hw_freed >= RX_POST_PKTS) {
+ p_rx_rbr_ring_t rx_rbr_p;
+ rx_rbr_p = rcrp->rx_rbr_p;
+ nxge_rx_reclaim_post_page(nxgep, rx_rbr_p);
+ }
+#endif
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_pkts_vring"));
+}
+
+
+/*
+ * This routine is the main packet receive processing function.
+ * It gets the packet type, error code, and buffer related
+ * information from the receive completion entry.
+ * How many completion entries to process is based on the number of packets
+ * queued by the hardware, a hardware maintained tail pointer
+ * and a configurable receive packet count.
+ *
+ * A chain of message blocks will be created as result of processing
+ * the completion entries. This chain of message blocks will be returned and
+ * a hardware control status register will be updated with the number of
+ * packets were removed from the hardware queue.
+ *
+ */
+#if !defined(_BIG_ENDIAN) && defined(RDC_NPI_DIRECT)
+mblk_t *
+nxge_rx_pkts(p_nxge_t nxgep, uint_t vindex, p_nxge_ldv_t ldvp,
+ p_rx_rcr_ring_t *rcrp, rx_dma_ctl_stat_t cs)
+#else
+mblk_t *
+nxge_rx_pkts(p_nxge_t nxgep, uint_t vindex, p_nxge_ldv_t ldvp,
+ p_rx_rcr_ring_t *rcrp)
+#endif
+{
+ npi_handle_t handle;
+ uint8_t channel;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t rcr_p;
+ uint32_t comp_rd_index;
+ p_rcr_entry_t rcr_desc_rd_head_p;
+ p_rcr_entry_t rcr_desc_rd_head_pp;
+#ifdef USE_TAIL_POINTER
+ p_rcr_entry_t rcr_desc_wt_tail_hw_pp;
+ addr44_t tail_addr_pp;
+#ifdef RDC_NPI_DIRECT
+ uint64_t value = 0;
+ uint64_t value2 = 0;
+#endif
+#endif
+ p_mblk_t nmp, mp_cont, head_mp, *tail_mp;
+ uint16_t qlen, nrcr_read, npkt_read;
+ uint32_t qlen_hw;
+ boolean_t multi;
+#ifdef USE_DYNAMIC_BLANKING
+ uint64_t rcr_cfg_b = 0x0ull;
+#endif
+
+#ifndef RDC_NPI_DIRECT
+ npi_status_t rs = NPI_SUCCESS;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts:vindex %d "
+ "channel %d", vindex, ldvp->channel));
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ return (NULL);
+ }
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ rcr_p = rx_rcr_rings->rcr_rings[vindex];
+ channel = rcr_p->rdc;
+ if (channel != ldvp->channel) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts:index %d "
+ "channel %d, and rcr channel %d not matched.",
+ vindex, ldvp->channel, channel));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts: START: rcr channel %d "
+ "head_p $%p head_pp $%p index %d ",
+ channel, rcr_p->rcr_desc_rd_head_p,
+ rcr_p->rcr_desc_rd_head_pp,
+ rcr_p->comp_rd_index));
+
+
+#ifdef RDC_NPI_DIRECT
+ qlen = RXDMA_REG_READ32(handle, RCRSTAT_A_REG, channel) & 0xffff;
+#else
+ rs = npi_rxdma_rdc_rcr_qlen_get(handle, channel, &qlen);
+ if (rs != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts:index %d "
+ "channel %d, get qlen failed 0x%08x",
+ vindex, ldvp->channel, rs));
+ return (NULL);
+ }
+#endif
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rx_pkts:rcr channel %d "
+ "qlen %d", channel, qlen));
+
+
+
+ if (!qlen) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts:rcr channel %d "
+ "qlen %d (no pkts)", channel, qlen));
+
+ return (NULL);
+ }
+
+ comp_rd_index = rcr_p->comp_rd_index;
+
+ rcr_desc_rd_head_p = rcr_p->rcr_desc_rd_head_p;
+ rcr_desc_rd_head_pp = rcr_p->rcr_desc_rd_head_pp;
+
+ /*
+ * Tail pointer is the io address!
+ */
+#ifdef USE_TAIL_POINTER
+ tail_addr_pp.addr = 0;
+
+#ifdef RDC_NPI_DIRECT
+ value = 0;
+ value2 = 0;
+ RXDMA_REG_READ64(handle, RCRSTAT_B_REG, channel, &value);
+ RXDMA_REG_READ64(handle, RCRSTAT_C_REG, channel, &value2);
+ rcr_desc_wt_tail_hw_pp = (p_rcr_entry_t)((value | (value2 << 32)));
+#else
+ rs = npi_rxdma_rdc_rcr_tail_get(handle, channel, &tail_addr_pp);
+ rcr_desc_wt_tail_hw_pp = (p_rcr_entry_t)tail_addr_pp.addr;
+#endif
+#endif
+
+ nrcr_read = npkt_read = 0;
+
+ /*
+ * Number of packets queued
+ * (The jumbo or multi packet will be counted as only one
+ * packets and it may take up more than one completion entry).
+ */
+#ifdef USE_TAIL_POINTER
+ qlen_hw = (qlen < rcr_p->max_receive_pkts) ?
+ qlen : rcr_p->max_receive_pkts;
+#else
+ qlen_hw = (qlen < nxge_max_rx_pkts) ?
+ qlen : nxge_max_rx_pkts;
+#endif
+ head_mp = NULL;
+ tail_mp = &head_mp;
+ nmp = mp_cont = NULL;
+ multi = B_FALSE;
+
+
+/* dynamic blanking */
+#ifdef USE_DYNAMIC_BLANKING
+ rcr_cfg_b = (qlen_hw << 16) | nxge_rx_intr_timeout;
+#endif
+
+#ifdef USE_TAIL_POINTER
+ while ((rcr_desc_rd_head_pp != rcr_desc_wt_tail_hw_pp) && qlen_hw &&
+ (npkt_read < rcr_p->max_receive_pkts)) {
+#else
+ while (qlen_hw) {
+#endif
+
+#ifdef NXGE_DEBUG
+ nxge_dump_rcr_entry(nxgep, rcr_desc_rd_head_p);
+#endif
+ /*
+ * Process one completion ring entry.
+ */
+ nxge_receive_packet(nxgep,
+ rcr_p, rcr_desc_rd_head_p, &multi, &nmp, &mp_cont);
+
+ /*
+ * message chaining modes
+ */
+ if (nmp && !multi) {
+ nmp->b_next = NULL;
+ *tail_mp = nmp;
+ tail_mp = &nmp->b_next;
+ nmp = mp_cont = NULL;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts: loop: rcr channel %d "
+ "before updating: multi %d "
+ "nrcr_read %d "
+ "npk read %d "
+ "head_pp $%p index %d ",
+ channel,
+ multi,
+ nrcr_read, npkt_read, rcr_desc_rd_head_pp,
+ comp_rd_index));
+
+ if (!multi) {
+ qlen_hw--;
+ npkt_read++;
+ }
+
+ /*
+ * Update the next read entry.
+ */
+ comp_rd_index = NEXT_ENTRY(comp_rd_index,
+ rcr_p->comp_wrap_mask);
+
+ rcr_desc_rd_head_p = NEXT_ENTRY_PTR(rcr_desc_rd_head_p,
+ rcr_p->rcr_desc_first_p,
+ rcr_p->rcr_desc_last_p);
+
+#ifdef USE_TAIL_POINTER
+ rcr_desc_rd_head_pp = NEXT_ENTRY_PTR(
+ rcr_desc_rd_head_pp,
+ rcr_p->rcr_desc_first_pp,
+ rcr_p->rcr_desc_last_pp);
+#endif
+
+ nrcr_read++;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rx_pkts: (SAM, process one packet) "
+ "nrcr_read %d",
+ nrcr_read));
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts: loop: rcr channel %d "
+ "multi %d "
+ "nrcr_read %d "
+ "npk read %d "
+ "head_pp $%p index %d ",
+ channel,
+ multi,
+ nrcr_read, npkt_read, rcr_desc_rd_head_pp,
+ comp_rd_index));
+
+ }
+
+ rcr_p->rcr_desc_rd_head_pp = rcr_desc_rd_head_pp;
+ rcr_p->comp_rd_index = comp_rd_index;
+ rcr_p->rcr_desc_rd_head_p = rcr_desc_rd_head_p;
+
+#ifdef USE_DYNAMIC_BLANKING
+ RXDMA_REG_WRITE64(handle, RCRCFIG_B_REG,
+ channel, rcr_cfg_b);
+#endif
+
+#ifdef RDC_NPI_DIRECT
+ cs.bits.ldw.pktread = npkt_read;
+ cs.bits.ldw.ptrread = nrcr_read;
+ RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG,
+ channel, cs.value);
+#else
+ rs = npi_rxdma_rdc_rcr_read_update(handle, channel,
+ npkt_read, nrcr_read);
+#endif
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rx_pkts: EXIT: rcr channel %d "
+ "head_pp $%p index %016llx ",
+ channel,
+ rcr_p->rcr_desc_rd_head_pp,
+ rcr_p->comp_rd_index));
+ /*
+ * Update RCR buffer pointer read and number of packets
+ * read.
+ */
+
+ *rcrp = rcr_p;
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rx_pkts"));
+ return (head_mp);
+}
+
+void
+nxge_receive_packet(p_nxge_t nxgep,
+ p_rx_rcr_ring_t rcr_p, p_rcr_entry_t rcr_desc_rd_head_p,
+ boolean_t *multi_p, mblk_t **mp, mblk_t **mp_cont)
+{
+ p_mblk_t nmp = NULL;
+ uint64_t multi;
+ uint64_t dcf_err;
+ uint8_t channel;
+
+ boolean_t first_entry = B_TRUE;
+ boolean_t is_tcp_udp = B_FALSE;
+ boolean_t buffer_free = B_FALSE;
+ boolean_t error_send_up = B_FALSE;
+ uint8_t error_type;
+ uint16_t l2_len;
+ uint16_t skip_len;
+ uint8_t pktbufsz_type;
+ uint64_t rcr_entry;
+ uint64_t *pkt_buf_addr_pp;
+ uint64_t *pkt_buf_addr_p;
+ uint32_t buf_offset;
+ uint32_t bsize;
+ uint32_t error_disp_cnt;
+ uint32_t msg_index;
+ p_rx_rbr_ring_t rx_rbr_p;
+ p_rx_msg_t *rx_msg_ring_p;
+ p_rx_msg_t rx_msg_p;
+ uint16_t sw_offset_bytes = 0, hdr_size = 0;
+ nxge_status_t status = NXGE_OK;
+ boolean_t is_valid = B_FALSE;
+ p_nxge_rx_ring_stats_t rdc_stats;
+
+ uint64_t pkt_type;
+ uint64_t frag;
+#ifdef NXGE_DEBUG
+ int dump_len;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "==> nxge_receive_packet"));
+ first_entry = (*mp == NULL) ? B_TRUE : B_FALSE;
+
+ rcr_entry = *((uint64_t *)rcr_desc_rd_head_p);
+
+ multi = (rcr_entry & RCR_MULTI_MASK);
+ dcf_err = (rcr_entry & RCR_DCF_ERROR_MASK);
+ pkt_type = (rcr_entry & RCR_PKT_TYPE_MASK);
+
+ error_type = ((rcr_entry & RCR_ERROR_MASK) >> RCR_ERROR_SHIFT);
+ frag = (rcr_entry & RCR_FRAG_MASK);
+
+ l2_len = ((rcr_entry & RCR_L2_LEN_MASK) >> RCR_L2_LEN_SHIFT);
+
+ pktbufsz_type = ((rcr_entry & RCR_PKTBUFSZ_MASK) >>
+ RCR_PKTBUFSZ_SHIFT);
+
+ pkt_buf_addr_pp = (uint64_t *)((rcr_entry & RCR_PKT_BUF_ADDR_MASK) <<
+ RCR_PKT_BUF_ADDR_SHIFT);
+
+ channel = rcr_p->rdc;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: entryp $%p entry 0x%0llx "
+ "pkt_buf_addr_pp $%p l2_len %d multi %d "
+ "error_type 0x%x pkt_type 0x%x "
+ "pktbufsz_type %d ",
+ rcr_desc_rd_head_p,
+ rcr_entry, pkt_buf_addr_pp, l2_len,
+ multi,
+ error_type,
+ pkt_type,
+ pktbufsz_type));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: entryp $%p entry 0x%0llx "
+ "pkt_buf_addr_pp $%p l2_len %d multi %d "
+ "error_type 0x%x pkt_type 0x%x ", rcr_desc_rd_head_p,
+ rcr_entry, pkt_buf_addr_pp, l2_len,
+ multi,
+ error_type,
+ pkt_type));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> (rbr) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ /* get the stats ptr */
+ rdc_stats = rcr_p->rdc_stats;
+
+ if (!l2_len) {
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_receive_packet: failed: l2 length is 0."));
+ return;
+ }
+
+ /* shift 6 bits to get the full io address */
+ pkt_buf_addr_pp = (uint64_t *)((uint64_t)pkt_buf_addr_pp <<
+ RCR_PKT_BUF_ADDR_SHIFT_FULL);
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> (rbr) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ rx_rbr_p = rcr_p->rx_rbr_p;
+ rx_msg_ring_p = rx_rbr_p->rx_msg_ring;
+
+ if (first_entry) {
+ hdr_size = (rcr_p->full_hdr_flag ? RXDMA_HDR_SIZE_FULL :
+ RXDMA_HDR_SIZE_DEFAULT);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_receive_packet: first entry 0x%016llx "
+ "pkt_buf_addr_pp $%p l2_len %d hdr %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len,
+ hdr_size));
+ }
+
+ MUTEX_ENTER(&rcr_p->lock);
+ MUTEX_ENTER(&rx_rbr_p->lock);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> (rbr 1) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ /*
+ * Packet buffer address in the completion entry points
+ * to the starting buffer address (offset 0).
+ * Use the starting buffer address to locate the corresponding
+ * kernel address.
+ */
+ status = nxge_rxbuf_pp_to_vp(nxgep, rx_rbr_p,
+ pktbufsz_type, pkt_buf_addr_pp, &pkt_buf_addr_p,
+ &buf_offset,
+ &msg_index);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> (rbr 2) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ if (status != NXGE_OK) {
+ MUTEX_EXIT(&rx_rbr_p->lock);
+ MUTEX_EXIT(&rcr_p->lock);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_receive_packet: found vaddr failed %d",
+ status));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> (rbr 3) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> (rbr 4 msgindex %d) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ msg_index, rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ rx_msg_p = rx_msg_ring_p[msg_index];
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> (rbr 4 msgindex %d) nxge_receive_packet: entry 0x%0llx "
+ "full pkt_buf_addr_pp $%p l2_len %d",
+ msg_index, rcr_entry, pkt_buf_addr_pp, l2_len));
+
+ switch (pktbufsz_type) {
+ case RCR_PKTBUFSZ_0:
+ bsize = rx_rbr_p->pkt_buf_size0_bytes;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: 0 buf %d", bsize));
+ break;
+ case RCR_PKTBUFSZ_1:
+ bsize = rx_rbr_p->pkt_buf_size1_bytes;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: 1 buf %d", bsize));
+ break;
+ case RCR_PKTBUFSZ_2:
+ bsize = rx_rbr_p->pkt_buf_size2_bytes;
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_receive_packet: 2 buf %d", bsize));
+ break;
+ case RCR_SINGLE_BLOCK:
+ bsize = rx_msg_p->block_size;
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: single %d", bsize));
+
+ break;
+ default:
+ MUTEX_EXIT(&rx_rbr_p->lock);
+ MUTEX_EXIT(&rcr_p->lock);
+ return;
+ }
+
+ DMA_COMMON_SYNC_OFFSET(rx_msg_p->buf_dma,
+ (buf_offset + sw_offset_bytes),
+ (hdr_size + l2_len),
+ DDI_DMA_SYNC_FORCPU);
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: after first dump:usage count"));
+
+ if (rx_msg_p->cur_usage_cnt == 0) {
+ if (rx_rbr_p->rbr_use_bcopy) {
+ atomic_inc_32(&rx_rbr_p->rbr_consumed);
+ if (rx_rbr_p->rbr_consumed <
+ rx_rbr_p->rbr_threshold_hi) {
+ if (rx_rbr_p->rbr_threshold_lo == 0 ||
+ ((rx_rbr_p->rbr_consumed >=
+ rx_rbr_p->rbr_threshold_lo) &&
+ (rx_rbr_p->rbr_bufsize_type >=
+ pktbufsz_type))) {
+ rx_msg_p->rx_use_bcopy = B_TRUE;
+ }
+ } else {
+ rx_msg_p->rx_use_bcopy = B_TRUE;
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: buf %d (new block) ",
+ bsize));
+
+ rx_msg_p->pkt_buf_size_code = pktbufsz_type;
+ rx_msg_p->pkt_buf_size = bsize;
+ rx_msg_p->cur_usage_cnt = 1;
+ if (pktbufsz_type == RCR_SINGLE_BLOCK) {
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: buf %d "
+ "(single block) ",
+ bsize));
+ /*
+ * Buffer can be reused once the free function
+ * is called.
+ */
+ rx_msg_p->max_usage_cnt = 1;
+ buffer_free = B_TRUE;
+ } else {
+ rx_msg_p->max_usage_cnt = rx_msg_p->block_size/bsize;
+ if (rx_msg_p->max_usage_cnt == 1) {
+ buffer_free = B_TRUE;
+ }
+ }
+ } else {
+ rx_msg_p->cur_usage_cnt++;
+ if (rx_msg_p->cur_usage_cnt == rx_msg_p->max_usage_cnt) {
+ buffer_free = B_TRUE;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "msgbuf index = %d l2len %d bytes usage %d max_usage %d ",
+ msg_index, l2_len,
+ rx_msg_p->cur_usage_cnt, rx_msg_p->max_usage_cnt));
+
+ if ((error_type) || (dcf_err)) {
+ rdc_stats->ierrors++;
+ if (dcf_err) {
+ rdc_stats->dcf_err++;
+#ifdef NXGE_DEBUG
+ if (!rdc_stats->dcf_err) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "nxge_receive_packet: channel %d dcf_err rcr"
+ " 0x%llx", channel, rcr_entry));
+ }
+#endif
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, NULL,
+ NXGE_FM_EREPORT_RDMC_DCF_ERR);
+ } else {
+ /* Update error stats */
+ error_disp_cnt = NXGE_ERROR_SHOW_MAX;
+ rdc_stats->errlog.compl_err_type = error_type;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, NULL,
+ NXGE_FM_EREPORT_RDMC_COMPLETION_ERR);
+
+ switch (error_type) {
+ case RCR_L2_ERROR:
+ rdc_stats->l2_err++;
+ if (rdc_stats->l2_err <
+ error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep,
+ NXGE_ERR_CTL,
+ " nxge_receive_packet:"
+ " channel %d RCR L2_ERROR",
+ channel));
+ break;
+ case RCR_L4_CSUM_ERROR:
+ error_send_up = B_TRUE;
+ rdc_stats->l4_cksum_err++;
+ if (rdc_stats->l4_cksum_err <
+ error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep,
+ NXGE_ERR_CTL,
+ " nxge_receive_packet:"
+ " channel %d"
+ " RCR L4_CSUM_ERROR",
+ channel));
+ break;
+ case RCR_FFLP_SOFT_ERROR:
+ error_send_up = B_TRUE;
+ rdc_stats->fflp_soft_err++;
+ if (rdc_stats->fflp_soft_err <
+ error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep,
+ NXGE_ERR_CTL,
+ " nxge_receive_packet:"
+ " channel %d"
+ " RCR FFLP_SOFT_ERROR",
+ channel));
+ break;
+ case RCR_ZCP_SOFT_ERROR:
+ error_send_up = B_TRUE;
+ rdc_stats->fflp_soft_err++;
+ if (rdc_stats->zcp_soft_err <
+ error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep,
+ NXGE_ERR_CTL,
+ " nxge_receive_packet:"
+ " Channel %d"
+ " RCR ZCP_SOFT_ERROR",
+ channel));
+ break;
+ default:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_receive_packet:"
+ " Channel %d"
+ " RCR entry 0x%llx"
+ " error 0x%x",
+ rcr_entry, channel,
+ error_type));
+ break;
+ }
+ }
+
+ /*
+ * Update and repost buffer block if max usage
+ * count is reached.
+ */
+ if (error_send_up == B_FALSE) {
+ if (buffer_free == B_TRUE) {
+
+#ifdef RX_USE_RECLAIM_POST
+ atomic_inc_32(&rx_rbr_p->hw_freed);
+#endif
+#ifdef RX_USE_BCOPY
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0;
+ rx_msg_p->pkt_buf_size = 0;
+ rx_rbr_p->rbr_wr_index =
+ ((rx_rbr_p->rbr_wr_index + 1) &
+ rx_rbr_p->rbr_wrap_mask);
+ rx_rbr_p->rbr_desc_vp[rx_rbr_p->rbr_wr_index] =
+ rx_msg_p->shifted_addr;
+ npi_rxdma_rdc_rbr_kick(
+ NXGE_DEV_NPI_HANDLE(nxgep),
+ rx_rbr_p->rdc, 1);
+#else
+ rx_msg_p->free = B_TRUE;
+#endif
+ }
+
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ atomic_inc_32(&rx_msg_p->pass_up_cnt);
+#else
+ atomic_inc_32(&rx_msg_p->ref_cnt);
+#endif
+ MUTEX_EXIT(&rx_rbr_p->lock);
+ MUTEX_EXIT(&rcr_p->lock);
+ nxge_freeb(rx_msg_p);
+ return;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: DMA sync second "));
+
+ /*
+ * Process the first 2/18 bytes header only if this
+ * is the first entry.
+ */
+ if (first_entry) {
+ status = nxge_rx_parse_header(nxgep, pkt_buf_addr_p, hdr_size);
+ if (status != NXGE_OK) {
+ if (buffer_free == B_TRUE) {
+
+#ifdef RX_USE_RECLAIM_POST
+ atomic_inc_32(&rx_rbr_p->hw_freed);
+#endif
+#ifdef RX_USE_BCOPY
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0;
+ rx_msg_p->pkt_buf_size = 0;
+ rx_rbr_p->rbr_wr_index =
+ ((rx_rbr_p->rbr_wr_index + 1) &
+ rx_rbr_p->rbr_wrap_mask);
+ rx_rbr_p->rbr_desc_vp[rx_rbr_p->rbr_wr_index] =
+ rx_msg_p->shifted_addr;
+ npi_rxdma_rdc_rbr_kick(
+ NXGE_DEV_NPI_HANDLE(nxgep),
+ rx_rbr_p->rdc, 1);
+#else
+ rx_msg_p->free = B_TRUE;
+#endif
+ }
+
+
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ atomic_inc_32(&rx_msg_p->pass_up_cnt);
+#else
+ atomic_inc_32(&rx_msg_p->ref_cnt);
+#endif
+ MUTEX_EXIT(&rx_rbr_p->lock);
+ MUTEX_EXIT(&rcr_p->lock);
+ nxge_freeb(rx_msg_p);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_receive_packet: parse header "
+ "error 0x%x", status));
+ return;
+ }
+ }
+
+ skip_len = sw_offset_bytes + hdr_size;
+ if (!rx_msg_p->rx_use_bcopy) {
+ nmp = nxge_dupb(rx_msg_p, buf_offset, bsize);
+ } else {
+ nmp = nxge_dupb_bcopy(rx_msg_p, buf_offset + skip_len, l2_len);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_receive_packet: use bcopy "
+ "rbr consumed %d "
+ "pktbufsz_type %d "
+ "offset %d "
+ "hdr_size %d l2_len %d "
+ "nmp->b_rptr $%p",
+ rx_rbr_p->rbr_consumed,
+ pktbufsz_type,
+ buf_offset, hdr_size, l2_len,
+ nmp->b_rptr));
+ }
+ if (nmp != NULL) {
+ if (!rx_msg_p->rx_use_bcopy) {
+ nmp->b_rptr = &nmp->b_rptr[skip_len];
+ nmp->b_wptr = &nmp->b_rptr[l2_len];
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_receive_packet after dupb: "
+ "rbr consumed %d "
+ "pktbufsz_type %d "
+ "nmp $%p rptr $%p wptr $%p "
+ "buf_offset %d bzise %d l2_len %d skip_len %d",
+ rx_rbr_p->rbr_consumed,
+ pktbufsz_type,
+ nmp, nmp->b_rptr, nmp->b_wptr,
+ buf_offset, bsize, l2_len, skip_len));
+ }
+ } else {
+ cmn_err(CE_WARN, "!nxge_receive_packet: "
+ "update stats (error)");
+ }
+ if (buffer_free == B_TRUE) {
+
+#ifdef RX_USE_RECLAIM_POST
+ atomic_inc_32(&rx_rbr_p->hw_freed);
+#endif
+#ifdef RX_USE_BCOPY
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0;
+ rx_msg_p->pkt_buf_size = 0;
+ rx_rbr_p->rbr_wr_index =
+ ((rx_rbr_p->rbr_wr_index + 1) &
+ rx_rbr_p->rbr_wrap_mask);
+ rx_rbr_p->rbr_desc_vp[rx_rbr_p->rbr_wr_index] =
+ rx_msg_p->shifted_addr;
+ npi_rxdma_rdc_rbr_kick(NXGE_DEV_NPI_HANDLE(nxgep),
+ rx_rbr_p->rdc, 1);
+#else
+ rx_msg_p->free = B_TRUE;
+#endif
+ }
+
+ /*
+ * ERROR, FRAG and PKT_TYPE are only reported
+ * in the first entry.
+ * If a packet is not fragmented and no error bit is set, then
+ * L4 checksum is OK.
+ */
+ is_valid = (nmp != NULL);
+ rdc_stats->ibytes += l2_len;
+ rdc_stats->ipackets++;
+ MUTEX_EXIT(&rx_rbr_p->lock);
+ MUTEX_EXIT(&rcr_p->lock);
+
+ if (rx_msg_p->free && rx_msg_p->rx_use_bcopy) {
+ atomic_inc_32(&rx_msg_p->ref_cnt);
+ nxge_freeb(rx_msg_p);
+ }
+
+ if (is_valid) {
+ if (first_entry) {
+ nmp->b_cont = NULL;
+ *mp = nmp;
+ *mp_cont = NULL;
+ } else {
+ nmp->b_cont = NULL;
+ if (*mp_cont == NULL) {
+ (*mp)->b_cont = nmp;
+ } else {
+ (*mp_cont)->b_cont = nmp;
+ }
+ *mp_cont = nmp;
+ }
+ }
+
+ /*
+ * Update stats and hardware checksuming.
+ */
+ if (is_valid && !multi) {
+
+ is_tcp_udp = ((pkt_type == RCR_PKT_IS_TCP ||
+ pkt_type == RCR_PKT_IS_UDP) ?
+ B_TRUE: B_FALSE);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_receive_packet: "
+ "is_valid 0x%x multi %d pkt %d frag %d error %d",
+ is_valid, multi, is_tcp_udp, frag, error_type));
+
+ if (is_tcp_udp && !frag && !error_type) {
+ (void) hcksum_assoc(nmp, NULL, NULL, 0, 0, 0, 0,
+ HCK_FULLCKSUM_OK | HCK_FULLCKSUM, 0);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_receive_packet: Full tcp/udp cksum "
+ "is_valid 0x%x multi %d pkt %d frag %d "
+ "error %d",
+ is_valid, multi, is_tcp_udp, frag, error_type));
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL,
+ "==> nxge_receive_packet: *mp 0x%016llx", *mp));
+
+ *multi_p = (multi == RCR_MULTI_MASK);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_receive_packet: "
+ "multi %d nmp 0x%016llx *mp 0x%016llx *mp_cont 0x%016llx",
+ *multi_p, nmp, *mp, *mp_cont));
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_rx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp,
+ rx_dma_ctl_stat_t cs)
+{
+ p_nxge_rx_ring_stats_t rdc_stats;
+ npi_handle_t handle;
+ npi_status_t rs;
+ boolean_t rxchan_fatal = B_FALSE;
+ boolean_t rxport_fatal = B_FALSE;
+ uint8_t channel;
+ uint8_t portn;
+ nxge_status_t status = NXGE_OK;
+ uint32_t error_disp_cnt = NXGE_ERROR_SHOW_MAX;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_err_evnts"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ channel = ldvp->channel;
+ portn = nxgep->mac.portnum;
+ rdc_stats = &nxgep->statsp->rdc_stats[ldvp->vdma_index];
+
+ if (cs.bits.hdw.rbr_tmout) {
+ rdc_stats->rx_rbr_tmout++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RBR_TMOUT);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts: rx_rbr_timeout"));
+ }
+ if (cs.bits.hdw.rsp_cnt_err) {
+ rdc_stats->rsp_cnt_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "rsp_cnt_err", channel));
+ }
+ if (cs.bits.hdw.byte_en_bus) {
+ rdc_stats->byte_en_bus++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: byte_en_bus", channel));
+ rxchan_fatal = B_TRUE;
+ }
+ if (cs.bits.hdw.rsp_dat_err) {
+ rdc_stats->rsp_dat_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rsp_dat_err", channel));
+ }
+ if (cs.bits.hdw.rcr_ack_err) {
+ rdc_stats->rcr_ack_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rcr_ack_err", channel));
+ }
+ if (cs.bits.hdw.dc_fifo_err) {
+ rdc_stats->dc_fifo_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR);
+ /* This is not a fatal error! */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "dc_fifo_err", channel));
+ rxport_fatal = B_TRUE;
+ }
+ if ((cs.bits.hdw.rcr_sha_par) || (cs.bits.hdw.rbr_pre_par)) {
+ if ((rs = npi_rxdma_ring_perr_stat_get(handle,
+ &rdc_stats->errlog.pre_par,
+ &rdc_stats->errlog.sha_par))
+ != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "rcr_sha_par: get perr", channel));
+ return (NXGE_ERROR | rs);
+ }
+ if (cs.bits.hdw.rcr_sha_par) {
+ rdc_stats->rcr_sha_par++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rcr_sha_par", channel));
+ }
+ if (cs.bits.hdw.rbr_pre_par) {
+ rdc_stats->rbr_pre_par++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rbr_pre_par", channel));
+ }
+ }
+ if (cs.bits.hdw.port_drop_pkt) {
+ rdc_stats->port_drop_pkt++;
+ if (rdc_stats->port_drop_pkt < error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts (channel %d): "
+ "port_drop_pkt", channel));
+ }
+ if (cs.bits.hdw.wred_drop) {
+ rdc_stats->wred_drop++;
+ NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "wred_drop", channel));
+ }
+ if (cs.bits.hdw.rbr_pre_empty) {
+ rdc_stats->rbr_pre_empty++;
+ if (rdc_stats->rbr_pre_empty < error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "rbr_pre_empty", channel));
+#if defined(RX_USE_RECLAIM_POST)
+ nxge_rx_reclaim_post_page(nxgep,
+ nxgep->rx_rbr_rings->rbr_rings[ldvp->vdma_index]);
+#endif
+ }
+ if (cs.bits.hdw.rcr_shadow_full) {
+ rdc_stats->rcr_shadow_full++;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "rcr_shadow_full", channel));
+ }
+ if (cs.bits.hdw.config_err) {
+ rdc_stats->config_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_CONFIG_ERR);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "config error", channel));
+ }
+ if (cs.bits.hdw.rcrincon) {
+ rdc_stats->rcrincon++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RCRINCON);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rcrincon error", channel));
+ }
+ if (cs.bits.hdw.rcrfull) {
+ rdc_stats->rcrfull++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RCRFULL);
+ rxchan_fatal = B_TRUE;
+ if (rdc_stats->rcrfull < error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rcrfull error", channel));
+ }
+ if (cs.bits.hdw.rbr_empty) {
+ rdc_stats->rbr_empty++;
+ if (rdc_stats->rbr_empty < error_disp_cnt)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "rbr empty error", channel));
+#if defined(RX_USE_RECLAIM_POST)
+ nxge_rx_reclaim_post_page(nxgep,
+ nxgep->rx_rbr_rings->rbr_rings[ldvp->vdma_index]);
+#endif
+ }
+ if (cs.bits.hdw.rbrfull) {
+ rdc_stats->rbrfull++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RBRFULL);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rbr_full error", channel));
+ }
+ if (cs.bits.hdw.rbrlogpage) {
+ rdc_stats->rbrlogpage++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_RBRLOGPAGE);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: rbr logical page error", channel));
+ }
+ if (cs.bits.hdw.cfiglogpage) {
+ rdc_stats->cfiglogpage++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, channel,
+ NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE);
+ rxchan_fatal = B_TRUE;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rx_err_evnts(channel %d): "
+ "fatal error: cfig logical page error", channel));
+ }
+
+ if (rxport_fatal) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rx_err_evnts: "
+ " fatal error on Port #%d\n",
+ portn));
+ status = nxge_ipp_fatal_err_recover(nxgep);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ if (rxchan_fatal) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rx_err_evnts: "
+ " fatal error on Channel #%d\n",
+ channel));
+ status = nxge_rxdma_fatal_err_recover(nxgep, channel);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "<== nxge_rx_err_evnts"));
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_map_rxdma(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_mbox_areas_t rx_mbox_areas_p;
+ p_rx_mbox_t *rx_mbox_p;
+ p_nxge_dma_pool_t dma_buf_poolp;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_common_t *dma_cntl_p;
+ uint32_t *num_chunks;
+ nxge_status_t status = NXGE_OK;
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ p_nxge_dma_common_t t_dma_buf_p;
+ p_nxge_dma_common_t t_dma_cntl_p;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_map_rxdma"));
+
+ dma_buf_poolp = nxgep->rx_buf_pool_p;
+ dma_cntl_poolp = nxgep->rx_cntl_pool_p;
+
+ if (!dma_buf_poolp->buf_allocated || !dma_cntl_poolp->buf_allocated) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_map_rxdma: buf not allocated"));
+ return (NXGE_ERROR);
+ }
+
+ ndmas = dma_buf_poolp->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_map_rxdma: no dma allocated"));
+ return (NXGE_ERROR);
+ }
+
+ num_chunks = dma_buf_poolp->num_chunks;
+ dma_buf_p = dma_buf_poolp->dma_buf_pool_p;
+ dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
+ rx_rbr_rings = (p_rx_rbr_rings_t)
+ KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP);
+ rbr_rings = (p_rx_rbr_ring_t *)KMEM_ZALLOC(
+ sizeof (p_rx_rbr_ring_t) * ndmas, KM_SLEEP);
+
+ rx_rcr_rings = (p_rx_rcr_rings_t)
+ KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP);
+ rcr_rings = (p_rx_rcr_ring_t *)KMEM_ZALLOC(
+ sizeof (p_rx_rcr_ring_t) * ndmas, KM_SLEEP);
+
+ rx_mbox_areas_p = (p_rx_mbox_areas_t)
+ KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP);
+ rx_mbox_p = (p_rx_mbox_t *)KMEM_ZALLOC(
+ sizeof (p_rx_mbox_t) * ndmas, KM_SLEEP);
+
+ /*
+ * Map descriptors from the buffer polls for each dam channel.
+ */
+ for (i = 0; i < ndmas; i++) {
+ /*
+ * Set up and prepare buffer blocks, descriptors
+ * and mailbox.
+ */
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ status = nxge_map_rxdma_channel(nxgep, channel,
+ (p_nxge_dma_common_t *)&dma_buf_p[i],
+ (p_rx_rbr_ring_t *)&rbr_rings[i],
+ num_chunks[i],
+ (p_nxge_dma_common_t *)&dma_cntl_p[i],
+ (p_rx_rcr_ring_t *)&rcr_rings[i],
+ (p_rx_mbox_t *)&rx_mbox_p[i]);
+ if (status != NXGE_OK) {
+ goto nxge_map_rxdma_fail1;
+ }
+ rbr_rings[i]->index = (uint16_t)i;
+ rcr_rings[i]->index = (uint16_t)i;
+ rcr_rings[i]->rdc_stats = &nxgep->statsp->rdc_stats[i];
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (nxgep->niu_type == N2_NIU && NXGE_DMA_BLOCK == 1) {
+ rbr_rings[i]->hv_set = B_FALSE;
+ t_dma_buf_p = (p_nxge_dma_common_t)dma_buf_p[i];
+ t_dma_cntl_p =
+ (p_nxge_dma_common_t)dma_cntl_p[i];
+
+ rbr_rings[i]->hv_rx_buf_base_ioaddr_pp =
+ (uint64_t)t_dma_buf_p->orig_ioaddr_pp;
+ rbr_rings[i]->hv_rx_buf_ioaddr_size =
+ (uint64_t)t_dma_buf_p->orig_alength;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel: "
+ "channel %d "
+ "data buf base io $%p ($%p) "
+ "size 0x%llx (%d 0x%x)",
+ channel,
+ rbr_rings[i]->hv_rx_buf_base_ioaddr_pp,
+ t_dma_cntl_p->ioaddr_pp,
+ rbr_rings[i]->hv_rx_buf_ioaddr_size,
+ t_dma_buf_p->orig_alength,
+ t_dma_buf_p->orig_alength));
+
+ rbr_rings[i]->hv_rx_cntl_base_ioaddr_pp =
+ (uint64_t)t_dma_cntl_p->orig_ioaddr_pp;
+ rbr_rings[i]->hv_rx_cntl_ioaddr_size =
+ (uint64_t)t_dma_cntl_p->orig_alength;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel: "
+ "channel %d "
+ "cntl base io $%p ($%p) "
+ "size 0x%llx (%d 0x%x)",
+ channel,
+ rbr_rings[i]->hv_rx_cntl_base_ioaddr_pp,
+ t_dma_cntl_p->ioaddr_pp,
+ rbr_rings[i]->hv_rx_cntl_ioaddr_size,
+ t_dma_cntl_p->orig_alength,
+ t_dma_cntl_p->orig_alength));
+ }
+
+#endif /* sun4v and NIU_LP_WORKAROUND */
+ }
+
+ rx_rbr_rings->ndmas = rx_rcr_rings->ndmas = ndmas;
+ rx_rbr_rings->rbr_rings = rbr_rings;
+ nxgep->rx_rbr_rings = rx_rbr_rings;
+ rx_rcr_rings->rcr_rings = rcr_rings;
+ nxgep->rx_rcr_rings = rx_rcr_rings;
+
+ rx_mbox_areas_p->rxmbox_areas = rx_mbox_p;
+ nxgep->rx_mbox_areas_p = rx_mbox_areas_p;
+
+ goto nxge_map_rxdma_exit;
+
+nxge_map_rxdma_fail1:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma: unmap rbr,rcr "
+ "(status 0x%x channel %d i %d)",
+ status, channel, i));
+ for (; i >= 0; i--) {
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ nxge_unmap_rxdma_channel(nxgep, channel,
+ rbr_rings[i],
+ rcr_rings[i],
+ rx_mbox_p[i]);
+ }
+
+ KMEM_FREE(rbr_rings, sizeof (p_rx_rbr_ring_t) * ndmas);
+ KMEM_FREE(rx_rbr_rings, sizeof (rx_rbr_rings_t));
+ KMEM_FREE(rcr_rings, sizeof (p_rx_rcr_ring_t) * ndmas);
+ KMEM_FREE(rx_rcr_rings, sizeof (rx_rcr_rings_t));
+ KMEM_FREE(rx_mbox_p, sizeof (p_rx_mbox_t) * ndmas);
+ KMEM_FREE(rx_mbox_areas_p, sizeof (rx_mbox_areas_t));
+
+nxge_map_rxdma_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_map_rxdma: "
+ "(status 0x%x channel %d)",
+ status, channel));
+
+ return (status);
+}
+
+static void
+nxge_unmap_rxdma(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_mbox_areas_t rx_mbox_areas_p;
+ p_rx_mbox_t *rx_mbox_p;
+ p_nxge_dma_pool_t dma_buf_poolp;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_unmap_rxdma"));
+
+ dma_buf_poolp = nxgep->rx_buf_pool_p;
+ dma_cntl_poolp = nxgep->rx_cntl_pool_p;
+
+ if (!dma_buf_poolp->buf_allocated || !dma_cntl_poolp->buf_allocated) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_unmap_rxdma: NULL buf pointers"));
+ return;
+ }
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_unmap_rxdma: NULL ring pointers"));
+ return;
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_unmap_rxdma: no channel"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma (ndmas %d)", ndmas));
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ rx_mbox_areas_p = nxgep->rx_mbox_areas_p;
+ rx_mbox_p = rx_mbox_areas_p->rxmbox_areas;
+ dma_buf_p = dma_buf_poolp->dma_buf_pool_p;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma (ndmas %d) channel %d",
+ ndmas, channel));
+ (void) nxge_unmap_rxdma_channel(nxgep, channel,
+ (p_rx_rbr_ring_t)rbr_rings[i],
+ (p_rx_rcr_ring_t)rcr_rings[i],
+ (p_rx_mbox_t)rx_mbox_p[i]);
+ }
+
+ KMEM_FREE(rx_rbr_rings, sizeof (rx_rbr_rings_t));
+ KMEM_FREE(rbr_rings, sizeof (p_rx_rbr_ring_t) * ndmas);
+ KMEM_FREE(rx_rcr_rings, sizeof (rx_rcr_rings_t));
+ KMEM_FREE(rcr_rings, sizeof (p_rx_rcr_ring_t) * ndmas);
+ KMEM_FREE(rx_mbox_areas_p, sizeof (rx_mbox_areas_t));
+ KMEM_FREE(rx_mbox_p, sizeof (p_rx_mbox_t) * ndmas);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_unmap_rxdma"));
+}
+
+nxge_status_t
+nxge_map_rxdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_nxge_dma_common_t *dma_buf_p, p_rx_rbr_ring_t *rbr_p,
+ uint32_t num_chunks,
+ p_nxge_dma_common_t *dma_cntl_p, p_rx_rcr_ring_t *rcr_p,
+ p_rx_mbox_t *rx_mbox_p)
+{
+ int status = NXGE_OK;
+
+ /*
+ * Set up and prepare buffer blocks, descriptors
+ * and mailbox.
+ */
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel (channel %d)", channel));
+ /*
+ * Receive buffer blocks
+ */
+ status = nxge_map_rxdma_channel_buf_ring(nxgep, channel,
+ dma_buf_p, rbr_p, num_chunks);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma_channel (channel %d): "
+ "map buffer failed 0x%x", channel, status));
+ goto nxge_map_rxdma_channel_exit;
+ }
+
+ /*
+ * Receive block ring, completion ring and mailbox.
+ */
+ status = nxge_map_rxdma_channel_cfg_ring(nxgep, channel,
+ dma_cntl_p, rbr_p, rcr_p, rx_mbox_p);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma_channel (channel %d): "
+ "map config failed 0x%x", channel, status));
+ goto nxge_map_rxdma_channel_fail2;
+ }
+
+ goto nxge_map_rxdma_channel_exit;
+
+nxge_map_rxdma_channel_fail3:
+ /* Free rbr, rcr */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma_channel: free rbr/rcr "
+ "(status 0x%x channel %d)",
+ status, channel));
+ nxge_unmap_rxdma_channel_cfg_ring(nxgep,
+ *rcr_p, *rx_mbox_p);
+
+nxge_map_rxdma_channel_fail2:
+ /* Free buffer blocks */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma_channel: free rx buffers"
+ "(nxgep 0x%x status 0x%x channel %d)",
+ nxgep, status, channel));
+ nxge_unmap_rxdma_channel_buf_ring(nxgep, *rbr_p);
+
+nxge_map_rxdma_channel_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_map_rxdma_channel: "
+ "(nxgep 0x%x status 0x%x channel %d)",
+ nxgep, status, channel));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_rxdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma_channel (channel %d)", channel));
+
+ /*
+ * unmap receive block ring, completion ring and mailbox.
+ */
+ (void) nxge_unmap_rxdma_channel_cfg_ring(nxgep,
+ rcr_p, rx_mbox_p);
+
+ /* unmap buffer blocks */
+ (void) nxge_unmap_rxdma_channel_buf_ring(nxgep, rbr_p);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_unmap_rxdma_channel"));
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_map_rxdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dma_cntl_p, p_rx_rbr_ring_t *rbr_p,
+ p_rx_rcr_ring_t *rcr_p, p_rx_mbox_t *rx_mbox_p)
+{
+ p_rx_rbr_ring_t rbrp;
+ p_rx_rcr_ring_t rcrp;
+ p_rx_mbox_t mboxp;
+ p_nxge_dma_common_t cntl_dmap;
+ p_nxge_dma_common_t dmap;
+ p_rx_msg_t *rx_msg_ring;
+ p_rx_msg_t rx_msg_p;
+ p_rbr_cfig_a_t rcfga_p;
+ p_rbr_cfig_b_t rcfgb_p;
+ p_rcrcfig_a_t cfga_p;
+ p_rcrcfig_b_t cfgb_p;
+ p_rxdma_cfig1_t cfig1_p;
+ p_rxdma_cfig2_t cfig2_p;
+ p_rbr_kick_t kick_p;
+ uint32_t dmaaddrp;
+ uint32_t *rbr_vaddrp;
+ uint32_t bkaddr;
+ nxge_status_t status = NXGE_OK;
+ int i;
+ uint32_t nxge_port_rcr_size;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_cfg_ring"));
+
+ cntl_dmap = *dma_cntl_p;
+
+ /* Map in the receive block ring */
+ rbrp = *rbr_p;
+ dmap = (p_nxge_dma_common_t)&rbrp->rbr_desc;
+ nxge_setup_dma_common(dmap, cntl_dmap, rbrp->rbb_max, 4);
+ /*
+ * Zero out buffer block ring descriptors.
+ */
+ bzero((caddr_t)dmap->kaddrp, dmap->alength);
+
+ rcfga_p = &(rbrp->rbr_cfga);
+ rcfgb_p = &(rbrp->rbr_cfgb);
+ kick_p = &(rbrp->rbr_kick);
+ rcfga_p->value = 0;
+ rcfgb_p->value = 0;
+ kick_p->value = 0;
+ rbrp->rbr_addr = dmap->dma_cookie.dmac_laddress;
+ rcfga_p->value = (rbrp->rbr_addr &
+ (RBR_CFIG_A_STDADDR_MASK |
+ RBR_CFIG_A_STDADDR_BASE_MASK));
+ rcfga_p->value |= ((uint64_t)rbrp->rbb_max << RBR_CFIG_A_LEN_SHIFT);
+
+ rcfgb_p->bits.ldw.bufsz0 = rbrp->pkt_buf_size0;
+ rcfgb_p->bits.ldw.vld0 = 1;
+ rcfgb_p->bits.ldw.bufsz1 = rbrp->pkt_buf_size1;
+ rcfgb_p->bits.ldw.vld1 = 1;
+ rcfgb_p->bits.ldw.bufsz2 = rbrp->pkt_buf_size2;
+ rcfgb_p->bits.ldw.vld2 = 1;
+ rcfgb_p->bits.ldw.bksize = nxgep->rx_bksize_code;
+
+ /*
+ * For each buffer block, enter receive block address to the ring.
+ */
+ rbr_vaddrp = (uint32_t *)dmap->kaddrp;
+ rbrp->rbr_desc_vp = (uint32_t *)dmap->kaddrp;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_cfg_ring: channel %d "
+ "rbr_vaddrp $%p", dma_channel, rbr_vaddrp));
+
+ rx_msg_ring = rbrp->rx_msg_ring;
+#ifdef RX_USE_RECLAIM_POST
+ for (i = 0; i < rbrp->rbb_max; i++) {
+#else
+ for (i = 0; i < rbrp->tnblocks; i++) {
+#endif
+ rx_msg_p = rx_msg_ring[i];
+ rx_msg_p->nxgep = nxgep;
+ rx_msg_p->rx_rbr_p = rbrp;
+ bkaddr = (uint32_t)
+ ((rx_msg_p->buf_dma.dma_cookie.dmac_laddress
+ >> RBR_BKADDR_SHIFT));
+ rx_msg_p->free = B_FALSE;
+ rx_msg_p->max_usage_cnt = 0xbaddcafe;
+
+ *rbr_vaddrp++ = bkaddr;
+ }
+
+ kick_p->bits.ldw.bkadd = rbrp->rbb_max;
+ rbrp->rbr_wr_index = (rbrp->rbb_max - 1);
+
+ rbrp->rbr_rd_index = 0;
+
+ rbrp->rbr_consumed = 0;
+ rbrp->rbr_use_bcopy = B_TRUE;
+ rbrp->rbr_bufsize_type = RCR_PKTBUFSZ_0;
+ /*
+ * Do bcopy on packets greater than bcopy size once
+ * the lo threshold is reached.
+ * This lo threshold should be less than the hi threshold.
+ *
+ * Do bcopy on every packet once the hi threshold is reached.
+ */
+ if (nxge_rx_threshold_lo >= nxge_rx_threshold_hi) {
+ /* default it to use hi */
+ nxge_rx_threshold_lo = nxge_rx_threshold_hi;
+ }
+
+ if (nxge_rx_buf_size_type > NXGE_RBR_TYPE2) {
+ nxge_rx_buf_size_type = NXGE_RBR_TYPE2;
+ }
+ rbrp->rbr_bufsize_type = nxge_rx_buf_size_type;
+
+ switch (nxge_rx_threshold_hi) {
+ default:
+ case NXGE_RX_COPY_NONE:
+ /* Do not do bcopy at all */
+ rbrp->rbr_use_bcopy = B_FALSE;
+ rbrp->rbr_threshold_hi = rbrp->rbb_max;
+ break;
+
+ case NXGE_RX_COPY_1:
+ case NXGE_RX_COPY_2:
+ case NXGE_RX_COPY_3:
+ case NXGE_RX_COPY_4:
+ case NXGE_RX_COPY_5:
+ case NXGE_RX_COPY_6:
+ case NXGE_RX_COPY_7:
+ rbrp->rbr_threshold_hi =
+ rbrp->rbb_max *
+ (nxge_rx_threshold_hi)/NXGE_RX_BCOPY_SCALE;
+ break;
+
+ case NXGE_RX_COPY_ALL:
+ rbrp->rbr_threshold_hi = 0;
+ break;
+ }
+
+ switch (nxge_rx_threshold_lo) {
+ default:
+ case NXGE_RX_COPY_NONE:
+ /* Do not do bcopy at all */
+ if (rbrp->rbr_use_bcopy) {
+ rbrp->rbr_use_bcopy = B_FALSE;
+ }
+ rbrp->rbr_threshold_lo = rbrp->rbb_max;
+ break;
+
+ case NXGE_RX_COPY_1:
+ case NXGE_RX_COPY_2:
+ case NXGE_RX_COPY_3:
+ case NXGE_RX_COPY_4:
+ case NXGE_RX_COPY_5:
+ case NXGE_RX_COPY_6:
+ case NXGE_RX_COPY_7:
+ rbrp->rbr_threshold_lo =
+ rbrp->rbb_max *
+ (nxge_rx_threshold_lo)/NXGE_RX_BCOPY_SCALE;
+ break;
+
+ case NXGE_RX_COPY_ALL:
+ rbrp->rbr_threshold_lo = 0;
+ break;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "nxge_map_rxdma_channel_cfg_ring: channel %d "
+ "rbb_max %d "
+ "rbrp->rbr_bufsize_type %d "
+ "rbb_threshold_hi %d "
+ "rbb_threshold_lo %d",
+ dma_channel,
+ rbrp->rbb_max,
+ rbrp->rbr_bufsize_type,
+ rbrp->rbr_threshold_hi,
+ rbrp->rbr_threshold_lo));
+
+ rbrp->page_valid.value = 0;
+ rbrp->page_mask_1.value = rbrp->page_mask_2.value = 0;
+ rbrp->page_value_1.value = rbrp->page_value_2.value = 0;
+ rbrp->page_reloc_1.value = rbrp->page_reloc_2.value = 0;
+ rbrp->page_hdl.value = 0;
+
+ rbrp->page_valid.bits.ldw.page0 = 1;
+ rbrp->page_valid.bits.ldw.page1 = 1;
+
+ /* Map in the receive completion ring */
+ rcrp = (p_rx_rcr_ring_t)
+ KMEM_ZALLOC(sizeof (rx_rcr_ring_t), KM_SLEEP);
+ rcrp->rdc = dma_channel;
+
+
+ nxge_port_rcr_size = nxgep->nxge_port_rcr_size;
+ rcrp->comp_size = nxge_port_rcr_size;
+ rcrp->comp_wrap_mask = nxge_port_rcr_size - 1;
+
+ rcrp->max_receive_pkts = nxge_max_rx_pkts;
+
+ dmap = (p_nxge_dma_common_t)&rcrp->rcr_desc;
+ nxge_setup_dma_common(dmap, cntl_dmap, rcrp->comp_size,
+ sizeof (rcr_entry_t));
+ rcrp->comp_rd_index = 0;
+ rcrp->comp_wt_index = 0;
+ rcrp->rcr_desc_rd_head_p = rcrp->rcr_desc_first_p =
+ (p_rcr_entry_t)DMA_COMMON_VPTR(rcrp->rcr_desc);
+ rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp =
+ (p_rcr_entry_t)DMA_COMMON_IOADDR(rcrp->rcr_desc);
+
+ rcrp->rcr_desc_last_p = rcrp->rcr_desc_rd_head_p +
+ (nxge_port_rcr_size - 1);
+ rcrp->rcr_desc_last_pp = rcrp->rcr_desc_rd_head_pp +
+ (nxge_port_rcr_size - 1);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_cfg_ring: "
+ "channel %d "
+ "rbr_vaddrp $%p "
+ "rcr_desc_rd_head_p $%p "
+ "rcr_desc_rd_head_pp $%p "
+ "rcr_desc_rd_last_p $%p "
+ "rcr_desc_rd_last_pp $%p ",
+ dma_channel,
+ rbr_vaddrp,
+ rcrp->rcr_desc_rd_head_p,
+ rcrp->rcr_desc_rd_head_pp,
+ rcrp->rcr_desc_last_p,
+ rcrp->rcr_desc_last_pp));
+
+ /*
+ * Zero out buffer block ring descriptors.
+ */
+ bzero((caddr_t)dmap->kaddrp, dmap->alength);
+
+ rcrp->full_hdr_flag = B_FALSE;
+ rcrp->sw_priv_hdr_len = 0;
+
+ cfga_p = &(rcrp->rcr_cfga);
+ cfgb_p = &(rcrp->rcr_cfgb);
+ cfga_p->value = 0;
+ cfgb_p->value = 0;
+ rcrp->rcr_addr = dmap->dma_cookie.dmac_laddress;
+ cfga_p->value = (rcrp->rcr_addr &
+ (RCRCFIG_A_STADDR_MASK |
+ RCRCFIG_A_STADDR_BASE_MASK));
+
+ rcfga_p->value |= ((uint64_t)rcrp->comp_size <<
+ RCRCFIG_A_LEN_SHIF);
+
+ /*
+ * Timeout should be set based on the system clock divider.
+ * The following timeout value of 1 assumes that the
+ * granularity (1000) is 3 microseconds running at 300MHz.
+ */
+ cfgb_p->bits.ldw.pthres = RXDMA_RCR_PTHRES_DEFAULT;
+ cfgb_p->bits.ldw.timeout = RXDMA_RCR_TO_DEFAULT;
+ cfgb_p->bits.ldw.entout = 1;
+
+ /* Map in the mailbox */
+ mboxp = (p_rx_mbox_t)
+ KMEM_ZALLOC(sizeof (rx_mbox_t), KM_SLEEP);
+ dmap = (p_nxge_dma_common_t)&mboxp->rx_mbox;
+ nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (rxdma_mailbox_t));
+ cfig1_p = (p_rxdma_cfig1_t)&mboxp->rx_cfg1;
+ cfig2_p = (p_rxdma_cfig2_t)&mboxp->rx_cfg2;
+ cfig1_p->value = cfig2_p->value = 0;
+
+ mboxp->mbox_addr = dmap->dma_cookie.dmac_laddress;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_cfg_ring: "
+ "channel %d cfg1 0x%016llx cfig2 0x%016llx cookie 0x%016llx",
+ dma_channel, cfig1_p->value, cfig2_p->value,
+ mboxp->mbox_addr));
+
+ dmaaddrp = (uint32_t)(dmap->dma_cookie.dmac_laddress >> 32
+ & 0xfff);
+ cfig1_p->bits.ldw.mbaddr_h = dmaaddrp;
+
+
+ dmaaddrp = (uint32_t)(dmap->dma_cookie.dmac_laddress & 0xffffffff);
+ dmaaddrp = (uint32_t)(dmap->dma_cookie.dmac_laddress &
+ RXDMA_CFIG2_MBADDR_L_MASK);
+
+ cfig2_p->bits.ldw.mbaddr = (dmaaddrp >> RXDMA_CFIG2_MBADDR_L_SHIFT);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_cfg_ring: "
+ "channel %d damaddrp $%p "
+ "cfg1 0x%016llx cfig2 0x%016llx",
+ dma_channel, dmaaddrp,
+ cfig1_p->value, cfig2_p->value));
+
+ cfig2_p->bits.ldw.full_hdr = rcrp->full_hdr_flag;
+ cfig2_p->bits.ldw.offset = rcrp->sw_priv_hdr_len;
+
+ rbrp->rx_rcr_p = rcrp;
+ rcrp->rx_rbr_p = rbrp;
+ *rcr_p = rcrp;
+ *rx_mbox_p = mboxp;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_map_rxdma_channel_cfg_ring status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_rxdma_channel_cfg_ring(p_nxge_t nxgep,
+ p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma_channel_cfg_ring: channel %d",
+ rcr_p->rdc));
+
+ KMEM_FREE(rcr_p, sizeof (rx_rcr_ring_t));
+ KMEM_FREE(rx_mbox_p, sizeof (rx_mbox_t));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_unmap_rxdma_channel_cfg_ring"));
+}
+
+static nxge_status_t
+nxge_map_rxdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel,
+ p_nxge_dma_common_t *dma_buf_p,
+ p_rx_rbr_ring_t *rbr_p, uint32_t num_chunks)
+{
+ p_rx_rbr_ring_t rbrp;
+ p_nxge_dma_common_t dma_bufp, tmp_bufp;
+ p_rx_msg_t *rx_msg_ring;
+ p_rx_msg_t rx_msg_p;
+ p_mblk_t mblk_p;
+
+ rxring_info_t *ring_info;
+ nxge_status_t status = NXGE_OK;
+ int i, j, index;
+ uint32_t size, bsize, nblocks, nmsgs;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_buf_ring: channel %d",
+ channel));
+
+ dma_bufp = tmp_bufp = *dma_buf_p;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_map_rxdma_channel_buf_ring: channel %d to map %d "
+ "chunks bufp 0x%016llx",
+ channel, num_chunks, dma_bufp));
+
+ nmsgs = 0;
+ for (i = 0; i < num_chunks; i++, tmp_bufp++) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_buf_ring: channel %d "
+ "bufp 0x%016llx nblocks %d nmsgs %d",
+ channel, tmp_bufp, tmp_bufp->nblocks, nmsgs));
+ nmsgs += tmp_bufp->nblocks;
+ }
+ if (!nmsgs) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_map_rxdma_channel_buf_ring: channel %d "
+ "no msg blocks",
+ channel));
+ status = NXGE_ERROR;
+ goto nxge_map_rxdma_channel_buf_ring_exit;
+ }
+
+ rbrp = (p_rx_rbr_ring_t)
+ KMEM_ZALLOC(sizeof (rx_rbr_ring_t), KM_SLEEP);
+
+ size = nmsgs * sizeof (p_rx_msg_t);
+ rx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP);
+ ring_info = (rxring_info_t *)KMEM_ZALLOC(sizeof (rxring_info_t),
+ KM_SLEEP);
+
+ MUTEX_INIT(&rbrp->lock, NULL, MUTEX_DRIVER,
+ (void *)nxgep->interrupt_cookie);
+ MUTEX_INIT(&rbrp->post_lock, NULL, MUTEX_DRIVER,
+ (void *)nxgep->interrupt_cookie);
+ rbrp->rdc = channel;
+ rbrp->num_blocks = num_chunks;
+ rbrp->tnblocks = nmsgs;
+ rbrp->rbb_max = nmsgs;
+ rbrp->rbr_max_size = nmsgs;
+ rbrp->rbr_wrap_mask = (rbrp->rbb_max - 1);
+
+ /*
+ * Buffer sizes suggested by NIU architect.
+ * 256, 512 and 2K.
+ */
+
+ rbrp->pkt_buf_size0 = RBR_BUFSZ0_256B;
+ rbrp->pkt_buf_size0_bytes = RBR_BUFSZ0_256_BYTES;
+ rbrp->npi_pkt_buf_size0 = SIZE_256B;
+
+ rbrp->pkt_buf_size1 = RBR_BUFSZ1_1K;
+ rbrp->pkt_buf_size1_bytes = RBR_BUFSZ1_1K_BYTES;
+ rbrp->npi_pkt_buf_size1 = SIZE_1KB;
+
+ rbrp->block_size = nxgep->rx_default_block_size;
+
+ if (!nxge_jumbo_enable) {
+ rbrp->pkt_buf_size2 = RBR_BUFSZ2_2K;
+ rbrp->pkt_buf_size2_bytes = RBR_BUFSZ2_2K_BYTES;
+ rbrp->npi_pkt_buf_size2 = SIZE_2KB;
+ } else {
+ if (rbrp->block_size >= 0x2000) {
+ rbrp->pkt_buf_size2 = RBR_BUFSZ2_8K;
+ rbrp->pkt_buf_size2_bytes = RBR_BUFSZ2_8K_BYTES;
+ rbrp->npi_pkt_buf_size2 = SIZE_8KB;
+ } else {
+ rbrp->pkt_buf_size2 = RBR_BUFSZ2_4K;
+ rbrp->pkt_buf_size2_bytes = RBR_BUFSZ2_4K_BYTES;
+ rbrp->npi_pkt_buf_size2 = SIZE_4KB;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_map_rxdma_channel_buf_ring: channel %d "
+ "actual rbr max %d rbb_max %d nmsgs %d "
+ "rbrp->block_size %d default_block_size %d "
+ "(config nxge_rbr_size %d nxge_rbr_spare_size %d)",
+ channel, rbrp->rbr_max_size, rbrp->rbb_max, nmsgs,
+ rbrp->block_size, nxgep->rx_default_block_size,
+ nxge_rbr_size, nxge_rbr_spare_size));
+
+ /* Map in buffers from the buffer pool. */
+ index = 0;
+ for (i = 0; i < rbrp->num_blocks; i++, dma_bufp++) {
+ bsize = dma_bufp->block_size;
+ nblocks = dma_bufp->nblocks;
+ ring_info->buffer[i].dvma_addr = (uint64_t)dma_bufp->ioaddr_pp;
+ ring_info->buffer[i].buf_index = i;
+ ring_info->buffer[i].buf_size = dma_bufp->alength;
+ ring_info->buffer[i].start_index = index;
+ ring_info->buffer[i].kaddr = (uint64_t)dma_bufp->kaddrp;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_map_rxdma_channel_buf_ring: map channel %d "
+ "chunk %d"
+ " nblocks %d chunk_size %x block_size 0x%x "
+ "dma_bufp $%p", channel, i,
+ dma_bufp->nblocks, ring_info->buffer[i].buf_size, bsize,
+ dma_bufp));
+
+ for (j = 0; j < nblocks; j++) {
+ if ((rx_msg_p = nxge_allocb(bsize, BPRI_LO,
+ dma_bufp)) == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "allocb failed"));
+ break;
+ }
+ rx_msg_ring[index] = rx_msg_p;
+ rx_msg_p->block_index = index;
+ rx_msg_p->shifted_addr = (uint32_t)
+ ((rx_msg_p->buf_dma.dma_cookie.dmac_laddress >>
+ RBR_BKADDR_SHIFT));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "index %d j %d rx_msg_p $%p",
+ index, j, rx_msg_p));
+
+ mblk_p = rx_msg_p->rx_mblk_p;
+ mblk_p->b_wptr = mblk_p->b_rptr + bsize;
+ index++;
+ rx_msg_p->buf_dma.dma_channel = channel;
+ }
+ }
+ if (i < rbrp->num_blocks) {
+ goto nxge_map_rxdma_channel_buf_ring_fail1;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "nxge_map_rxdma_channel_buf_ring: done buf init "
+ "channel %d msg block entries %d",
+ channel, index));
+ ring_info->block_size_mask = bsize - 1;
+ rbrp->rx_msg_ring = rx_msg_ring;
+ rbrp->dma_bufp = dma_buf_p;
+ rbrp->ring_info = ring_info;
+
+ status = nxge_rxbuf_index_info_init(nxgep, rbrp);
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_map_rxdma_channel_buf_ring: "
+ "channel %d done buf info init", channel));
+
+#ifdef RX_USE_RECLAIM_POST
+ rbrp->msg_cnt = index;
+ rbrp->hw_freed = 0;
+ nmsgs = index - (index / 4);
+ rbrp->rbb_max = nmsgs;
+ rbrp->rbr_max_size = nmsgs;
+ rbrp->rbr_wrap_mask = (rbrp->rbr_max_size - 1);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_rxdma_channel_buf_ring: after channel %d "
+ "actual rbr max %d rbb_max %d nmsgs %d "
+ "rbrp->block_size %d default_block_size %d "
+ "(config nxge_rbr_size %d nxge_rbr_spare_size %d)",
+ channel, rbrp->rbr_max_size, rbrp->rbb_max, nmsgs,
+ rbrp->block_size, nxgep->rx_default_block_size,
+ nxge_rbr_size, nxge_rbr_spare_size));
+#endif
+
+ *rbr_p = rbrp;
+ goto nxge_map_rxdma_channel_buf_ring_exit;
+
+nxge_map_rxdma_channel_buf_ring_fail1:
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_map_rxdma_channel_buf_ring: failed channel (0x%x)",
+ channel, status));
+
+ index--;
+ for (; index >= 0; index--) {
+ rx_msg_p = rx_msg_ring[index];
+ if (rx_msg_p != NULL) {
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ rx_msg_p->release = B_TRUE;
+#endif
+ nxge_freeb(rx_msg_p);
+ rx_msg_ring[index] = NULL;
+ }
+ }
+nxge_map_rxdma_channel_buf_ring_fail:
+ MUTEX_DESTROY(&rbrp->post_lock);
+ MUTEX_DESTROY(&rbrp->lock);
+ KMEM_FREE(ring_info, sizeof (rxring_info_t));
+ KMEM_FREE(rx_msg_ring, size);
+ KMEM_FREE(rbrp, sizeof (rx_rbr_ring_t));
+
+nxge_map_rxdma_channel_buf_ring_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_map_rxdma_channel_buf_ring status 0x%08x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_rxdma_channel_buf_ring(p_nxge_t nxgep,
+ p_rx_rbr_ring_t rbr_p)
+{
+ p_rx_msg_t *rx_msg_ring;
+ p_rx_msg_t rx_msg_p;
+ rxring_info_t *ring_info;
+ int i;
+ uint32_t size;
+#ifdef NXGE_DEBUG
+ int num_chunks;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma_channel_buf_ring"));
+ if (rbr_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_unmap_rxdma_channel_buf_ring: NULL rbrp"));
+ return;
+ }
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_unmap_rxdma_channel_buf_ring: channel %d",
+ rbr_p->rdc));
+
+ rx_msg_ring = rbr_p->rx_msg_ring;
+ ring_info = rbr_p->ring_info;
+
+ if (rx_msg_ring == NULL || ring_info == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_unmap_rxdma_channel_buf_ring: "
+ "rx_msg_ring $%p ring_info $%p",
+ rx_msg_p, ring_info));
+ return;
+ }
+
+#ifdef NXGE_DEBUG
+ num_chunks = rbr_p->num_blocks;
+#endif
+ size = rbr_p->tnblocks * sizeof (p_rx_msg_t);
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_unmap_rxdma_channel_buf_ring: channel %d chunks %d "
+ "tnblocks %d (max %d) size ptrs %d ",
+ rbr_p->rdc, num_chunks,
+ rbr_p->tnblocks, rbr_p->rbr_max_size, size));
+
+ for (i = 0; i < rbr_p->tnblocks; i++) {
+ rx_msg_p = rx_msg_ring[i];
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ " nxge_unmap_rxdma_channel_buf_ring: "
+ "rx_msg_p $%p",
+ rx_msg_p));
+ if (rx_msg_p != NULL) {
+ nxge_freeb(rx_msg_p);
+ rx_msg_ring[i] = NULL;
+ }
+ }
+
+ MUTEX_DESTROY(&rbr_p->post_lock);
+ MUTEX_DESTROY(&rbr_p->lock);
+ KMEM_FREE(ring_info, sizeof (rxring_info_t));
+ KMEM_FREE(rx_msg_ring, size);
+ KMEM_FREE(rbr_p, sizeof (rx_rbr_ring_t));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "<== nxge_unmap_rxdma_channel_buf_ring"));
+}
+
+static nxge_status_t
+nxge_rxdma_hw_start_common(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_start_common"));
+
+ /*
+ * Load the sharable parameters by writing to the
+ * function zero control registers. These FZC registers
+ * should be initialized only once for the entire chip.
+ */
+ (void) nxge_init_fzc_rx_common(nxgep);
+
+ /*
+ * Initialize the RXDMA port specific FZC control configurations.
+ * These FZC registers are pertaining to each port.
+ */
+ (void) nxge_init_fzc_rxdma_port(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_start_common"));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_rxdma_hw_stop_common(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_stop_common"));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_stop_common"));
+}
+
+static nxge_status_t
+nxge_rxdma_hw_start(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_rcr_ring_t *rcr_rings;
+ p_rx_mbox_areas_t rx_mbox_areas_p;
+ p_rx_mbox_t *rx_mbox_p;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_start"));
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_hw_start: NULL ring pointers"));
+ return (NXGE_ERROR);
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (ndmas == 0) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_hw_start: no dma channel allocated"));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_start (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+ rcr_rings = rx_rcr_rings->rcr_rings;
+ rx_mbox_areas_p = nxgep->rx_mbox_areas_p;
+ if (rx_mbox_areas_p) {
+ rx_mbox_p = rx_mbox_areas_p->rxmbox_areas;
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ channel = rbr_rings[i]->rdc;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_start (ndmas %d) channel %d",
+ ndmas, channel));
+ status = nxge_rxdma_start_channel(nxgep, channel,
+ (p_rx_rbr_ring_t)rbr_rings[i],
+ (p_rx_rcr_ring_t)rcr_rings[i],
+ (p_rx_mbox_t)rx_mbox_p[i]);
+ if (status != NXGE_OK) {
+ goto nxge_rxdma_hw_start_fail1;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_start: "
+ "rx_rbr_rings 0x%016llx rings 0x%016llx",
+ rx_rbr_rings, rx_rcr_rings));
+
+ goto nxge_rxdma_hw_start_exit;
+
+nxge_rxdma_hw_start_fail1:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_hw_start: disable "
+ "(status 0x%x channel %d i %d)", status, channel, i));
+ for (; i >= 0; i--) {
+ channel = rbr_rings[i]->rdc;
+ (void) nxge_rxdma_stop_channel(nxgep, channel);
+ }
+
+nxge_rxdma_hw_start_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_start: (status 0x%x)", status));
+
+ return (status);
+}
+
+static void
+nxge_rxdma_hw_stop(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rbr_ring_t *rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_stop"));
+
+ rx_rbr_rings = nxgep->rx_rbr_rings;
+ rx_rcr_rings = nxgep->rx_rcr_rings;
+ if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_hw_stop: NULL ring pointers"));
+ return;
+ }
+ ndmas = rx_rbr_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "<== nxge_rxdma_hw_stop: no dma channel allocated"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_stop (ndmas %d)", ndmas));
+
+ rbr_rings = rx_rbr_rings->rbr_rings;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = rbr_rings[i]->rdc;
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_hw_stop (ndmas %d) channel %d",
+ ndmas, channel));
+ (void) nxge_rxdma_stop_channel(nxgep, channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_hw_stop: "
+ "rx_rbr_rings 0x%016llx rings 0x%016llx",
+ rx_rbr_rings, rx_rcr_rings));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_rxdma_hw_stop"));
+}
+
+
+static nxge_status_t
+nxge_rxdma_start_channel(p_nxge_t nxgep, uint16_t channel,
+ p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p)
+
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ rx_dma_ctl_stat_t cs;
+ rx_dma_ent_msk_t ent_mask;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "nxge_rxdma_start_channel: "
+ "npi handle addr $%p acc $%p",
+ nxgep->npi_handle.regp, nxgep->npi_handle.regh));
+
+ /* Reset RXDMA channel */
+ rs = npi_rxdma_cfg_rdc_reset(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_start_channel: "
+ "reset rxdma failed (0x%08x channel %d)",
+ status, channel));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_start_channel: reset done: channel %d",
+ channel));
+
+ /*
+ * Initialize the RXDMA channel specific FZC control
+ * configurations. These FZC registers are pertaining
+ * to each RX channel (logical pages).
+ */
+ status = nxge_init_fzc_rxdma_channel(nxgep,
+ channel, rbr_p, rcr_p, mbox_p);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_start_channel: "
+ "init fzc rxdma failed (0x%08x channel %d)",
+ status, channel));
+ return (status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_start_channel: fzc done"));
+
+ /*
+ * Zero out the shadow and prefetch ram.
+ */
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel: "
+ "ram done"));
+
+ /* Set up the interrupt event masks. */
+ ent_mask.value = 0;
+ ent_mask.value |= RX_DMA_ENT_MSK_RBREMPTY_MASK;
+ rs = npi_rxdma_event_mask(handle, OP_SET, channel,
+ &ent_mask);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_start_channel: "
+ "init rxdma event masks failed (0x%08x channel %d)",
+ status, channel));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel: "
+ "event done: channel %d (mask 0x%016llx)",
+ channel, ent_mask.value));
+
+ /* Initialize the receive DMA control and status register */
+ cs.value = 0;
+ cs.bits.hdw.mex = 1;
+ cs.bits.hdw.rcrthres = 1;
+ cs.bits.hdw.rcrto = 1;
+ cs.bits.hdw.rbr_empty = 1;
+ status = nxge_init_rxdma_channel_cntl_stat(nxgep, channel, &cs);
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel: "
+ "channel %d rx_dma_cntl_stat 0x%0016llx", channel, cs.value));
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_start_channel: "
+ "init rxdma control register failed (0x%08x channel %d",
+ status, channel));
+ return (status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel: "
+ "control done - channel %d cs 0x%016llx", channel, cs.value));
+
+ /*
+ * Load RXDMA descriptors, buffers, mailbox,
+ * initialise the receive DMA channels and
+ * enable each DMA channel.
+ */
+ status = nxge_enable_rxdma_channel(nxgep,
+ channel, rbr_p, rcr_p, mbox_p);
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rxdma_start_channel: "
+ " init enable rxdma failed (0x%08x channel %d)",
+ status, channel));
+ return (status);
+ }
+
+ ent_mask.value = 0;
+ ent_mask.value |= (RX_DMA_ENT_MSK_WRED_DROP_MASK |
+ RX_DMA_ENT_MSK_PTDROP_PKT_MASK);
+ rs = npi_rxdma_event_mask(handle, OP_SET, channel,
+ &ent_mask);
+ if (rs != NPI_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_start_channel: "
+ "init rxdma event masks failed (0x%08x channel %d)",
+ status, channel));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_rxdma_start_channel: "
+ "control done - channel %d cs 0x%016llx", channel, cs.value));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL,
+ "==> nxge_rxdma_start_channel: enable done"));
+
+ NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_rxdma_start_channel"));
+
+ return (NXGE_OK);
+}
+
+static nxge_status_t
+nxge_rxdma_stop_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ rx_dma_ctl_stat_t cs;
+ rx_dma_ent_msk_t ent_mask;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_stop_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "nxge_rxdma_stop_channel: "
+ "npi handle addr $%p acc $%p",
+ nxgep->npi_handle.regp, nxgep->npi_handle.regh));
+
+ /* Reset RXDMA channel */
+ rs = npi_rxdma_cfg_rdc_reset(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rxdma_stop_channel: "
+ " reset rxdma failed (0x%08x channel %d)",
+ rs, channel));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_stop_channel: reset done"));
+
+ /* Set up the interrupt event masks. */
+ ent_mask.value = RX_DMA_ENT_MSK_ALL;
+ rs = npi_rxdma_event_mask(handle, OP_SET, channel,
+ &ent_mask);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_rxdma_stop_channel: "
+ "set rxdma event masks failed (0x%08x channel %d)",
+ rs, channel));
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_stop_channel: event done"));
+
+ /* Initialize the receive DMA control and status register */
+ cs.value = 0;
+ status = nxge_init_rxdma_channel_cntl_stat(nxgep, channel,
+ &cs);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_stop_channel: control "
+ " to default (all 0s) 0x%08x", cs.value));
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rxdma_stop_channel: init rxdma"
+ " control register failed (0x%08x channel %d",
+ status, channel));
+ return (status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL,
+ "==> nxge_rxdma_stop_channel: control done"));
+
+ /* disable dma channel */
+ status = nxge_disable_rxdma_channel(nxgep, channel);
+
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rxdma_stop_channel: "
+ " init enable rxdma failed (0x%08x channel %d)",
+ status, channel));
+ return (status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep,
+ RX_CTL, "==> nxge_rxdma_stop_channel: disable done"));
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_stop_channel"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_rxdma_handle_sys_errors(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ p_nxge_rdc_sys_stats_t statsp;
+ rx_ctl_dat_fifo_stat_t stat;
+ uint32_t zcp_err_status;
+ uint32_t ipp_err_status;
+ nxge_status_t status = NXGE_OK;
+ npi_status_t rs = NPI_SUCCESS;
+ boolean_t my_err = B_FALSE;
+
+ handle = nxgep->npi_handle;
+ statsp = (p_nxge_rdc_sys_stats_t)&nxgep->statsp->rdc_sys_stats;
+
+ rs = npi_rxdma_rxctl_fifo_error_intr_get(handle, &stat);
+
+ if (rs != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+ if (stat.bits.ldw.id_mismatch) {
+ statsp->id_mismatch++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, NULL,
+ NXGE_FM_EREPORT_RDMC_ID_MISMATCH);
+ /* Global fatal error encountered */
+ }
+
+ if ((stat.bits.ldw.zcp_eop_err) || (stat.bits.ldw.ipp_eop_err)) {
+ switch (nxgep->mac.portnum) {
+ case 0:
+ if ((stat.bits.ldw.zcp_eop_err & FIFO_EOP_PORT0) ||
+ (stat.bits.ldw.ipp_eop_err & FIFO_EOP_PORT0)) {
+ my_err = B_TRUE;
+ zcp_err_status = stat.bits.ldw.zcp_eop_err;
+ ipp_err_status = stat.bits.ldw.ipp_eop_err;
+ }
+ break;
+ case 1:
+ if ((stat.bits.ldw.zcp_eop_err & FIFO_EOP_PORT1) ||
+ (stat.bits.ldw.ipp_eop_err & FIFO_EOP_PORT1)) {
+ my_err = B_TRUE;
+ zcp_err_status = stat.bits.ldw.zcp_eop_err;
+ ipp_err_status = stat.bits.ldw.ipp_eop_err;
+ }
+ break;
+ case 2:
+ if ((stat.bits.ldw.zcp_eop_err & FIFO_EOP_PORT2) ||
+ (stat.bits.ldw.ipp_eop_err & FIFO_EOP_PORT2)) {
+ my_err = B_TRUE;
+ zcp_err_status = stat.bits.ldw.zcp_eop_err;
+ ipp_err_status = stat.bits.ldw.ipp_eop_err;
+ }
+ break;
+ case 3:
+ if ((stat.bits.ldw.zcp_eop_err & FIFO_EOP_PORT3) ||
+ (stat.bits.ldw.ipp_eop_err & FIFO_EOP_PORT3)) {
+ my_err = B_TRUE;
+ zcp_err_status = stat.bits.ldw.zcp_eop_err;
+ ipp_err_status = stat.bits.ldw.ipp_eop_err;
+ }
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+ }
+
+ if (my_err) {
+ status = nxge_rxdma_handle_port_errors(nxgep, ipp_err_status,
+ zcp_err_status);
+ if (status != NXGE_OK)
+ return (status);
+ }
+
+ return (NXGE_OK);
+}
+
+static nxge_status_t
+nxge_rxdma_handle_port_errors(p_nxge_t nxgep, uint32_t ipp_status,
+ uint32_t zcp_status)
+{
+ boolean_t rxport_fatal = B_FALSE;
+ p_nxge_rdc_sys_stats_t statsp;
+ nxge_status_t status = NXGE_OK;
+ uint8_t portn;
+
+ portn = nxgep->mac.portnum;
+ statsp = (p_nxge_rdc_sys_stats_t)&nxgep->statsp->rdc_sys_stats;
+
+ if (ipp_status & (0x1 << portn)) {
+ statsp->ipp_eop_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR);
+ rxport_fatal = B_TRUE;
+ }
+
+ if (zcp_status & (0x1 << portn)) {
+ statsp->zcp_eop_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR);
+ rxport_fatal = B_TRUE;
+ }
+
+ if (rxport_fatal) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_rxdma_handle_port_error: "
+ " fatal error on Port #%d\n",
+ portn));
+ status = nxge_rx_port_fatal_err_recover(nxgep);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_rxdma_fatal_err_recover(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ p_rx_rbr_ring_t rbrp;
+ p_rx_rcr_ring_t rcrp;
+ p_rx_mbox_t mboxp;
+ rx_dma_ent_msk_t ent_mask;
+ p_nxge_dma_common_t dmap;
+ int ring_idx;
+ uint32_t ref_cnt;
+ p_rx_msg_t rx_msg_p;
+ int i;
+ uint32_t nxge_port_rcr_size;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rxdma_fatal_err_recover"));
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from RxDMAChannel#%d error...", channel));
+
+ /*
+ * Stop the dma channel waits for the stop done.
+ * If the stop done bit is not set, then create
+ * an error.
+ */
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Rx DMA stop..."));
+
+ ring_idx = nxge_rxdma_get_ring_index(nxgep, channel);
+ rbrp = (p_rx_rbr_ring_t)nxgep->rx_rbr_rings->rbr_rings[ring_idx];
+ rcrp = (p_rx_rcr_ring_t)nxgep->rx_rcr_rings->rcr_rings[ring_idx];
+
+ MUTEX_ENTER(&rcrp->lock);
+ MUTEX_ENTER(&rbrp->lock);
+ MUTEX_ENTER(&rbrp->post_lock);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Disable RxDMA channel..."));
+
+ rs = npi_rxdma_cfg_rdc_disable(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_disable_rxdma_channel:failed"));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Disable RxDMA interrupt..."));
+
+ /* Disable interrupt */
+ ent_mask.value = RX_DMA_ENT_MSK_ALL;
+ rs = npi_rxdma_event_mask(handle, OP_SET, channel, &ent_mask);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rxdma_stop_channel: "
+ "set rxdma event masks failed (channel %d)",
+ channel));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "RxDMA channel reset..."));
+
+ /* Reset RXDMA channel */
+ rs = npi_rxdma_cfg_rdc_reset(handle, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rxdma_fatal_err_recover: "
+ " reset rxdma failed (channel %d)", channel));
+ goto fail;
+ }
+
+ nxge_port_rcr_size = nxgep->nxge_port_rcr_size;
+
+ mboxp =
+ (p_rx_mbox_t)nxgep->rx_mbox_areas_p->rxmbox_areas[ring_idx];
+
+ rbrp->rbr_wr_index = (rbrp->rbb_max - 1);
+ rbrp->rbr_rd_index = 0;
+
+ rcrp->comp_rd_index = 0;
+ rcrp->comp_wt_index = 0;
+ rcrp->rcr_desc_rd_head_p = rcrp->rcr_desc_first_p =
+ (p_rcr_entry_t)DMA_COMMON_VPTR(rcrp->rcr_desc);
+ rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp =
+ (p_rcr_entry_t)DMA_COMMON_IOADDR(rcrp->rcr_desc);
+
+ rcrp->rcr_desc_last_p = rcrp->rcr_desc_rd_head_p +
+ (nxge_port_rcr_size - 1);
+ rcrp->rcr_desc_last_pp = rcrp->rcr_desc_rd_head_pp +
+ (nxge_port_rcr_size - 1);
+
+ dmap = (p_nxge_dma_common_t)&rcrp->rcr_desc;
+ bzero((caddr_t)dmap->kaddrp, dmap->alength);
+
+ cmn_err(CE_NOTE, "!rbr entries = %d\n", rbrp->rbr_max_size);
+
+ for (i = 0; i < rbrp->rbr_max_size; i++) {
+ rx_msg_p = rbrp->rx_msg_ring[i];
+ ref_cnt = rx_msg_p->ref_cnt;
+ if (ref_cnt != 1) {
+
+#ifdef lint
+ ref_cnt = ref_cnt;
+#endif
+ } else if (rx_msg_p->cur_usage_cnt != rx_msg_p->max_usage_cnt) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "buf[%d]: cur_usage_cnt = %d "
+ "max_usage_cnt = %d\n", i,
+ rx_msg_p->cur_usage_cnt,
+ rx_msg_p->max_usage_cnt));
+ } else {
+ /* Buffer can be re-posted */
+ rx_msg_p->free = B_TRUE;
+ rx_msg_p->cur_usage_cnt = 0;
+ rx_msg_p->max_usage_cnt = 0xbaddcafe;
+ rx_msg_p->pkt_buf_size = 0;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "RxDMA channel re-start..."));
+
+ status = nxge_rxdma_start_channel(nxgep, channel, rbrp, rcrp, mboxp);
+ if (status != NXGE_OK) {
+ goto fail;
+ }
+
+ MUTEX_EXIT(&rbrp->post_lock);
+ MUTEX_EXIT(&rbrp->lock);
+ MUTEX_EXIT(&rcrp->lock);
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Successful, RxDMAChannel#%d Restored",
+ channel));
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_fatal_err_recover"));
+
+ return (NXGE_OK);
+fail:
+ MUTEX_EXIT(&rbrp->post_lock);
+ MUTEX_EXIT(&rbrp->lock);
+ MUTEX_EXIT(&rcrp->lock);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+
+ return (NXGE_ERROR | rs);
+}
+
+nxge_status_t
+nxge_rx_port_fatal_err_recover(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ p_nxge_dma_common_t *dma_buf_p;
+ uint16_t channel;
+ int ndmas;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rx_port_fatal_err_recover"));
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from RxPort error..."));
+ /* Disable RxMAC */
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Disable RxMAC...\n"));
+ if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
+ goto fail;
+
+ NXGE_DELAY(1000);
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Stop all RxDMA channels..."));
+
+ ndmas = nxgep->rx_buf_pool_p->ndmas;
+ dma_buf_p = nxgep->rx_buf_pool_p->dma_buf_pool_p;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ if (nxge_rxdma_fatal_err_recover(nxgep, channel) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Could not recover channel %d",
+ channel));
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Reset IPP..."));
+
+ /* Reset IPP */
+ if (nxge_ipp_reset(nxgep) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_port_fatal_err_recover: "
+ "Failed to reset IPP"));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Reset RxMAC..."));
+
+ /* Reset RxMAC */
+ if (nxge_rx_mac_reset(nxgep) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_port_fatal_err_recover: "
+ "Failed to reset RxMAC"));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Re-initialize IPP..."));
+
+ /* Re-Initialize IPP */
+ if (nxge_ipp_init(nxgep) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_port_fatal_err_recover: "
+ "Failed to init IPP"));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Re-initialize RxMAC..."));
+
+ /* Re-Initialize RxMAC */
+ if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_port_fatal_err_recover: "
+ "Failed to reset RxMAC"));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "Re-enable RxMAC..."));
+
+ /* Re-enable RxMAC */
+ if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_rx_port_fatal_err_recover: "
+ "Failed to enable RxMAC"));
+ goto fail;
+ }
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Successful, RxPort Restored"));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+ return (status);
+}
+
+void
+nxge_rxdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan)
+{
+ rx_dma_ctl_stat_t cs;
+ rx_ctl_dat_fifo_stat_t cdfs;
+
+ switch (err_id) {
+ case NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR:
+ case NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR:
+ case NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR:
+ case NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
+ case NXGE_FM_EREPORT_RDMC_RBR_TMOUT:
+ case NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR:
+ case NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS:
+ case NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR:
+ case NXGE_FM_EREPORT_RDMC_RCRINCON:
+ case NXGE_FM_EREPORT_RDMC_RCRFULL:
+ case NXGE_FM_EREPORT_RDMC_RBRFULL:
+ case NXGE_FM_EREPORT_RDMC_RBRLOGPAGE:
+ case NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE:
+ case NXGE_FM_EREPORT_RDMC_CONFIG_ERR:
+ RXDMA_REG_READ64(nxgep->npi_handle, RX_DMA_CTL_STAT_DBG_REG,
+ chan, &cs.value);
+ if (err_id == NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR)
+ cs.bits.hdw.rcr_ack_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR)
+ cs.bits.hdw.dc_fifo_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR)
+ cs.bits.hdw.rcr_sha_par = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
+ cs.bits.hdw.rbr_pre_par = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RBR_TMOUT)
+ cs.bits.hdw.rbr_tmout = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR)
+ cs.bits.hdw.rsp_cnt_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS)
+ cs.bits.hdw.byte_en_bus = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR)
+ cs.bits.hdw.rsp_dat_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_CONFIG_ERR)
+ cs.bits.hdw.config_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RCRINCON)
+ cs.bits.hdw.rcrincon = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RCRFULL)
+ cs.bits.hdw.rcrfull = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RBRFULL)
+ cs.bits.hdw.rbrfull = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_RBRLOGPAGE)
+ cs.bits.hdw.rbrlogpage = 1;
+ else if (err_id == NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE)
+ cs.bits.hdw.cfiglogpage = 1;
+ cmn_err(CE_NOTE, "!Write 0x%lx to RX_DMA_CTL_STAT_DBG_REG\n",
+ cs.value);
+ RXDMA_REG_WRITE64(nxgep->npi_handle, RX_DMA_CTL_STAT_DBG_REG,
+ chan, cs.value);
+ break;
+ case NXGE_FM_EREPORT_RDMC_ID_MISMATCH:
+ case NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR:
+ case NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR:
+ cdfs.value = 0;
+ if (err_id == NXGE_FM_EREPORT_RDMC_ID_MISMATCH)
+ cdfs.bits.ldw.id_mismatch = (1 << nxgep->mac.portnum);
+ else if (err_id == NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR)
+ cdfs.bits.ldw.zcp_eop_err = (1 << nxgep->mac.portnum);
+ else if (err_id == NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR)
+ cdfs.bits.ldw.ipp_eop_err = (1 << nxgep->mac.portnum);
+ cmn_err(CE_NOTE,
+ "!Write 0x%lx to RX_CTL_DAT_FIFO_STAT_DBG_REG\n",
+ cdfs.value);
+ RXDMA_REG_WRITE64(nxgep->npi_handle,
+ RX_CTL_DAT_FIFO_STAT_DBG_REG, chan, cdfs.value);
+ break;
+ case NXGE_FM_EREPORT_RDMC_DCF_ERR:
+ break;
+ case NXGE_FM_EREPORT_RDMC_COMPLETION_ERR:
+ break;
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_send.c b/usr/src/uts/sun4v/io/nxge/nxge_send.c
new file mode 100644
index 0000000000..f57c978da8
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_send.c
@@ -0,0 +1,1037 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+
+extern uint32_t nxge_reclaim_pending;
+extern uint32_t nxge_bcopy_thresh;
+extern uint32_t nxge_dvma_thresh;
+extern uint32_t nxge_dma_stream_thresh;
+extern uint32_t nxge_tx_minfree;
+extern uint32_t nxge_tx_intr_thres;
+extern uint32_t nxge_tx_max_gathers;
+extern uint32_t nxge_tx_tiny_pack;
+extern uint32_t nxge_tx_use_bcopy;
+extern uint32_t nxge_tx_lb_policy;
+extern uint32_t nxge_no_tx_lb;
+
+typedef struct _mac_tx_hint {
+ uint16_t sap;
+ uint16_t vid;
+ void *hash;
+} mac_tx_hint_t, *p_mac_tx_hint_t;
+
+int nxge_tx_lb_ring_1(p_mblk_t, uint32_t, p_mac_tx_hint_t);
+
+int
+nxge_start(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, p_mblk_t mp)
+{
+ int status = 0;
+ p_tx_desc_t tx_desc_ring_vp;
+ npi_handle_t npi_desc_handle;
+ nxge_os_dma_handle_t tx_desc_dma_handle;
+ p_tx_desc_t tx_desc_p;
+ p_tx_msg_t tx_msg_ring;
+ p_tx_msg_t tx_msg_p;
+ tx_desc_t tx_desc, *tmp_desc_p;
+ tx_desc_t sop_tx_desc, *sop_tx_desc_p;
+ p_tx_pkt_header_t hdrp;
+ p_tx_pkt_hdr_all_t pkthdrp;
+ uint8_t npads = 0;
+ uint64_t dma_ioaddr;
+ uint32_t dma_flags;
+ int last_bidx;
+ uint8_t *b_rptr;
+ caddr_t kaddr;
+ uint32_t nmblks;
+ uint32_t ngathers;
+ uint32_t clen;
+ int len;
+ uint32_t pkt_len, pack_len, min_len;
+ uint32_t bcopy_thresh;
+ int i, cur_index, sop_index;
+ uint16_t tail_index;
+ boolean_t tail_wrap = B_FALSE;
+ nxge_dma_common_t desc_area;
+ nxge_os_dma_handle_t dma_handle;
+ ddi_dma_cookie_t dma_cookie;
+ npi_handle_t npi_handle;
+ p_mblk_t nmp;
+ p_mblk_t t_mp;
+ uint32_t ncookies;
+ boolean_t good_packet;
+ boolean_t mark_mode = B_FALSE;
+ p_nxge_stats_t statsp;
+ p_nxge_tx_ring_stats_t tdc_stats;
+ t_uscalar_t start_offset = 0;
+ t_uscalar_t stuff_offset = 0;
+ t_uscalar_t end_offset = 0;
+ t_uscalar_t value = 0;
+ t_uscalar_t cksum_flags = 0;
+ boolean_t cksum_on = B_FALSE;
+ uint32_t boff = 0;
+ uint64_t tot_xfer_len = 0, tmp_len = 0;
+ boolean_t header_set = B_FALSE;
+#ifdef NXGE_DEBUG
+ p_tx_desc_t tx_desc_ring_pp;
+ p_tx_desc_t tx_desc_pp;
+ tx_desc_t *save_desc_p;
+ int dump_len;
+ int sad_len;
+ uint64_t sad;
+ int xfer_len;
+ uint32_t msgsize;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: tx dma channel %d", tx_ring_p->tdc));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: Starting tdc %d desc pending %d",
+ tx_ring_p->tdc, tx_ring_p->descs_pending));
+
+ statsp = nxgep->statsp;
+
+ if (nxgep->statsp->port_stats.lb_mode == nxge_lb_normal) {
+ if ((!statsp->mac_stats.link_up) ||
+ (FM_GET_DEVSTATE(nxgep) <= DDI_DEVSTATE_DEGRADED)) {
+ freemsg(mp);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: "
+ "link not up or LB mode"));
+ goto nxge_start_fail1;
+ }
+ }
+
+ hcksum_retrieve(mp, NULL, NULL, &start_offset,
+ &stuff_offset, &end_offset, &value, &cksum_flags);
+ if (!NXGE_IS_VLAN_PACKET(mp->b_rptr)) {
+ start_offset += sizeof (ether_header_t);
+ stuff_offset += sizeof (ether_header_t);
+ } else {
+ start_offset += sizeof (struct ether_vlan_header);
+ stuff_offset += sizeof (struct ether_vlan_header);
+ }
+
+ if (cksum_flags & HCK_PARTIALCKSUM) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: cksum_flags 0x%x (partial checksum) ",
+ cksum_flags));
+ cksum_on = B_TRUE;
+ }
+
+#ifdef NXGE_DEBUG
+ if (tx_ring_p->descs_pending) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: "
+ "desc pending %d ", tx_ring_p->descs_pending));
+ }
+
+ dump_len = (int)(MBLKL(mp));
+ dump_len = (dump_len > 128) ? 128: dump_len;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: tdc %d: dumping ...: b_rptr $%p "
+ "(Before header reserve: ORIGINAL LEN %d)",
+ tx_ring_p->tdc,
+ mp->b_rptr,
+ dump_len));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: dump packets "
+ "(IP ORIGINAL b_rptr $%p): %s", mp->b_rptr,
+ nxge_dump_packet((char *)mp->b_rptr, dump_len)));
+#endif
+
+ MUTEX_ENTER(&tx_ring_p->lock);
+ tdc_stats = tx_ring_p->tdc_stats;
+ mark_mode = (tx_ring_p->descs_pending &&
+ ((tx_ring_p->tx_ring_size - tx_ring_p->descs_pending)
+ < nxge_tx_minfree));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "TX Descriptor ring is channel %d mark mode %d",
+ tx_ring_p->tdc, mark_mode));
+
+ if (!nxge_txdma_reclaim(nxgep, tx_ring_p, nxge_tx_minfree)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "TX Descriptor ring is full: channel %d",
+ tx_ring_p->tdc));
+ cas32((uint32_t *)&tx_ring_p->queueing, 0, 1);
+ tdc_stats->tx_no_desc++;
+ MUTEX_EXIT(&tx_ring_p->lock);
+ if (nxgep->resched_needed && !nxgep->resched_running) {
+ nxgep->resched_running = B_TRUE;
+ ddi_trigger_softintr(nxgep->resched_id);
+ }
+ status = 1;
+ goto nxge_start_fail1;
+ }
+
+ nmp = mp;
+ i = sop_index = tx_ring_p->wr_index;
+ nmblks = 0;
+ ngathers = 0;
+ pkt_len = 0;
+ pack_len = 0;
+ clen = 0;
+ last_bidx = -1;
+ good_packet = B_TRUE;
+
+ desc_area = tx_ring_p->tdc_desc;
+ npi_handle = desc_area.npi_handle;
+ npi_desc_handle.regh = (nxge_os_acc_handle_t)
+ DMA_COMMON_ACC_HANDLE(desc_area);
+ tx_desc_ring_vp = (p_tx_desc_t)DMA_COMMON_VPTR(desc_area);
+#ifdef NXGE_DEBUG
+ tx_desc_ring_pp = (p_tx_desc_t)DMA_COMMON_IOADDR(desc_area);
+#endif
+ tx_desc_dma_handle = (nxge_os_dma_handle_t)
+ DMA_COMMON_HANDLE(desc_area);
+ tx_msg_ring = tx_ring_p->tx_msg_ring;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: wr_index %d i %d",
+ sop_index, i));
+
+#ifdef NXGE_DEBUG
+ msgsize = msgdsize(nmp);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(1): wr_index %d i %d msgdsize %d",
+ sop_index, i, msgsize));
+#endif
+ /*
+ * The first 16 bytes of the premapped buffer are reserved
+ * for header. No padding will be used.
+ */
+ pkt_len = pack_len = boff = TX_PKT_HEADER_SIZE;
+ if (nxge_tx_use_bcopy) {
+ bcopy_thresh = (nxge_bcopy_thresh - TX_PKT_HEADER_SIZE);
+ } else {
+ bcopy_thresh = (TX_BCOPY_SIZE - TX_PKT_HEADER_SIZE);
+ }
+ while (nmp) {
+ good_packet = B_TRUE;
+ b_rptr = nmp->b_rptr;
+ len = MBLKL(nmp);
+ if (len <= 0) {
+ nmp = nmp->b_cont;
+ continue;
+ }
+ nmblks++;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(1): nmblks %d "
+ "len %d pkt_len %d pack_len %d",
+ nmblks, len, pkt_len, pack_len));
+ /*
+ * Hardware limits the transfer length to 4K.
+ * If len is more than 4K, we need to break
+ * nmp into two chunks: Make first chunk smaller
+ * than 4K. The second chunk will be broken into
+ * less than 4K (if needed) during the next pass.
+ */
+ if (len > TX_MAX_TRANSFER_LENGTH) {
+ t_mp = dupb(nmp);
+ nmp->b_wptr = nmp->b_rptr + TX_MAX_TRANSFER_LENGTH;
+ t_mp->b_rptr = nmp->b_wptr;
+ t_mp->b_cont = nmp->b_cont;
+ nmp->b_cont = t_mp;
+
+ len = MBLKL(nmp);
+ }
+
+ tx_desc.value = 0;
+ tx_desc_p = &tx_desc_ring_vp[i];
+#ifdef NXGE_DEBUG
+ tx_desc_pp = &tx_desc_ring_pp[i];
+#endif
+ tx_msg_p = &tx_msg_ring[i];
+ npi_desc_handle.regp = (uint64_t)tx_desc_p;
+ if (!header_set &&
+ ((!nxge_tx_use_bcopy && (len > TX_BCOPY_SIZE)) ||
+ (len >= bcopy_thresh))) {
+ header_set = B_TRUE;
+ bcopy_thresh += TX_PKT_HEADER_SIZE;
+ boff = 0;
+ pack_len = 0;
+ kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma);
+ hdrp = (p_tx_pkt_header_t)kaddr;
+ clen = pkt_len;
+ dma_handle = tx_msg_p->buf_dma_handle;
+ dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma);
+ (void) ddi_dma_sync(dma_handle,
+ i * nxge_bcopy_thresh, nxge_bcopy_thresh,
+ DDI_DMA_SYNC_FORDEV);
+
+ tx_msg_p->flags.dma_type = USE_BCOPY;
+ goto nxge_start_control_header_only;
+ }
+
+ pkt_len += len;
+ pack_len += len;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(3): "
+ "desc entry %d "
+ "DESC IOADDR $%p "
+ "desc_vp $%p tx_desc_p $%p "
+ "desc_pp $%p tx_desc_pp $%p "
+ "len %d pkt_len %d pack_len %d",
+ i,
+ DMA_COMMON_IOADDR(desc_area),
+ tx_desc_ring_vp, tx_desc_p,
+ tx_desc_ring_pp, tx_desc_pp,
+ len, pkt_len, pack_len));
+
+ if (len < bcopy_thresh) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(4): "
+ "USE BCOPY: "));
+ if (nxge_tx_tiny_pack) {
+ uint32_t blst =
+ TXDMA_DESC_NEXT_INDEX(i, -1,
+ tx_ring_p->tx_wrap_mask);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(5): pack"));
+ if ((pack_len <= bcopy_thresh) &&
+ (last_bidx == blst)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: pack(6) "
+ "(pkt_len %d pack_len %d)",
+ pkt_len, pack_len));
+ i = blst;
+ tx_desc_p = &tx_desc_ring_vp[i];
+#ifdef NXGE_DEBUG
+ tx_desc_pp = &tx_desc_ring_pp[i];
+#endif
+ tx_msg_p = &tx_msg_ring[i];
+ boff = pack_len - len;
+ ngathers--;
+ } else if (pack_len > bcopy_thresh) {
+ pack_len = len;
+ boff = 0;
+ bcopy_thresh = nxge_bcopy_thresh;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(7): > max NEW "
+ "bcopy thresh %d "
+ "pkt_len %d pack_len %d(next)",
+ bcopy_thresh,
+ pkt_len, pack_len));
+ }
+ last_bidx = i;
+ }
+ kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma);
+ if ((boff == TX_PKT_HEADER_SIZE) && (nmblks == 1)) {
+ hdrp = (p_tx_pkt_header_t)kaddr;
+ header_set = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(7_x2): "
+ "pkt_len %d pack_len %d (new hdrp $%p)",
+ pkt_len, pack_len, hdrp));
+ }
+ tx_msg_p->flags.dma_type = USE_BCOPY;
+ kaddr += boff;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(8): "
+ "USE BCOPY: before bcopy "
+ "DESC IOADDR $%p entry %d "
+ "bcopy packets %d "
+ "bcopy kaddr $%p "
+ "bcopy ioaddr (SAD) $%p "
+ "bcopy clen %d "
+ "bcopy boff %d",
+ DMA_COMMON_IOADDR(desc_area), i,
+ tdc_stats->tx_hdr_pkts,
+ kaddr,
+ dma_ioaddr,
+ clen,
+ boff));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: "
+ "1USE BCOPY: "));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: "
+ "2USE BCOPY: "));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: "
+ "last USE BCOPY: copy from b_rptr $%p "
+ "to KADDR $%p (len %d offset %d",
+ b_rptr, kaddr, len, boff));
+
+ bcopy(b_rptr, kaddr, len);
+
+#ifdef NXGE_DEBUG
+ dump_len = (len > 128) ? 128: len;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: dump packets "
+ "(After BCOPY len %d)"
+ "(b_rptr $%p): %s", len, nmp->b_rptr,
+ nxge_dump_packet((char *)nmp->b_rptr,
+ dump_len)));
+#endif
+
+ dma_handle = tx_msg_p->buf_dma_handle;
+ dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma);
+ (void) ddi_dma_sync(dma_handle,
+ i * nxge_bcopy_thresh, nxge_bcopy_thresh,
+ DDI_DMA_SYNC_FORDEV);
+ clen = len + boff;
+ tdc_stats->tx_hdr_pkts++;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(9): "
+ "USE BCOPY: "
+ "DESC IOADDR $%p entry %d "
+ "bcopy packets %d "
+ "bcopy kaddr $%p "
+ "bcopy ioaddr (SAD) $%p "
+ "bcopy clen %d "
+ "bcopy boff %d",
+ DMA_COMMON_IOADDR(desc_area),
+ i,
+ tdc_stats->tx_hdr_pkts,
+ kaddr,
+ dma_ioaddr,
+ clen,
+ boff));
+ } else {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(12): "
+ "USE DVMA: len %d", len));
+ tx_msg_p->flags.dma_type = USE_DMA;
+ dma_flags = DDI_DMA_WRITE;
+ if (len < nxge_dma_stream_thresh) {
+ dma_flags |= DDI_DMA_CONSISTENT;
+ } else {
+ dma_flags |= DDI_DMA_STREAMING;
+ }
+
+ dma_handle = tx_msg_p->dma_handle;
+ status = ddi_dma_addr_bind_handle(dma_handle, NULL,
+ (caddr_t)b_rptr, len, dma_flags,
+ DDI_DMA_DONTWAIT, NULL,
+ &dma_cookie, &ncookies);
+ if (status == DDI_DMA_MAPPED) {
+ dma_ioaddr = dma_cookie.dmac_laddress;
+ len = (int)dma_cookie.dmac_size;
+ clen = (uint32_t)dma_cookie.dmac_size;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(12_1): "
+ "USE DVMA: len %d clen %d "
+ "ngathers %d",
+ len, clen,
+ ngathers));
+
+ npi_desc_handle.regp = (uint64_t)tx_desc_p;
+ while (ncookies > 1) {
+ ngathers++;
+ /*
+ * this is the fix for multiple
+ * cookies, which are basicaly
+ * a descriptor entry, we don't set
+ * SOP bit as well as related fields
+ */
+
+ (void) npi_txdma_desc_gather_set(
+ npi_desc_handle,
+ &tx_desc,
+ (ngathers -1),
+ mark_mode,
+ ngathers,
+ dma_ioaddr,
+ clen);
+
+ tx_msg_p->tx_msg_size = clen;
+#if NXGE_DEBUG
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: DMA "
+ "ncookie %d "
+ "ngathers %d "
+ "dma_ioaddr $%p len %d"
+ "desc $%p descp $%p (%d)",
+ ncookies,
+ ngathers,
+ dma_ioaddr, clen,
+ *tx_desc_p, tx_desc_p, i));
+#endif
+
+
+ ddi_dma_nextcookie(dma_handle,
+ &dma_cookie);
+ dma_ioaddr =
+ dma_cookie.dmac_laddress;
+
+ len = (int)dma_cookie.dmac_size;
+ clen = (uint32_t)dma_cookie.dmac_size;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(12_2): "
+ "USE DVMA: len %d clen %d ",
+ len, clen));
+
+ i = TXDMA_DESC_NEXT_INDEX(i, 1,
+ tx_ring_p->tx_wrap_mask);
+ tx_desc_p = &tx_desc_ring_vp[i];
+
+ npi_desc_handle.regp =
+ (uint64_t)tx_desc_p;
+ tx_msg_p = &tx_msg_ring[i];
+ tx_msg_p->flags.dma_type = USE_NONE;
+ tx_desc.value = 0;
+
+ ncookies--;
+ }
+ tdc_stats->tx_ddi_pkts++;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start:"
+ "DMA: ddi packets %d",
+ tdc_stats->tx_ddi_pkts));
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "dma mapping failed for %d "
+ "bytes addr $%p flags %x (%d)",
+ len, b_rptr, status, status));
+ good_packet = B_FALSE;
+ tdc_stats->tx_dma_bind_fail++;
+ tx_msg_p->flags.dma_type = USE_NONE;
+ goto nxge_start_fail2;
+ }
+ } /* ddi dvma */
+
+ nmp = nmp->b_cont;
+nxge_start_control_header_only:
+ npi_desc_handle.regp = (uint64_t)tx_desc_p;
+ ngathers++;
+
+ if (ngathers == 1) {
+#ifdef NXGE_DEBUG
+ save_desc_p = &sop_tx_desc;
+#endif
+ sop_tx_desc_p = &sop_tx_desc;
+ sop_tx_desc_p->value = 0;
+ sop_tx_desc_p->bits.hdw.tr_len = clen;
+ sop_tx_desc_p->bits.hdw.sad = dma_ioaddr >> 32;
+ sop_tx_desc_p->bits.ldw.sad = dma_ioaddr & 0xffffffff;
+ } else {
+#ifdef NXGE_DEBUG
+ save_desc_p = &tx_desc;
+#endif
+ tmp_desc_p = &tx_desc;
+ tmp_desc_p->value = 0;
+ tmp_desc_p->bits.hdw.tr_len = clen;
+ tmp_desc_p->bits.hdw.sad = dma_ioaddr >> 32;
+ tmp_desc_p->bits.ldw.sad = dma_ioaddr & 0xffffffff;
+
+ tx_desc_p->value = tmp_desc_p->value;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(13): "
+ "Desc_entry %d ngathers %d "
+ "desc_vp $%p tx_desc_p $%p "
+ "len %d clen %d pkt_len %d pack_len %d nmblks %d "
+ "dma_ioaddr (SAD) $%p mark %d",
+ i, ngathers,
+ tx_desc_ring_vp, tx_desc_p,
+ len, clen, pkt_len, pack_len, nmblks,
+ dma_ioaddr, mark_mode));
+
+#ifdef NXGE_DEBUG
+ npi_desc_handle.nxgep = nxgep;
+ npi_desc_handle.function.function = nxgep->function_num;
+ npi_desc_handle.function.instance = nxgep->instance;
+ sad = (save_desc_p->value & TX_PKT_DESC_SAD_MASK);
+ xfer_len = ((save_desc_p->value & TX_PKT_DESC_TR_LEN_MASK) >>
+ TX_PKT_DESC_TR_LEN_SHIFT);
+
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\t: value 0x%llx\n"
+ "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\t"
+ "mark %d sop %d\n",
+ save_desc_p->value,
+ sad,
+ save_desc_p->bits.hdw.tr_len,
+ xfer_len,
+ save_desc_p->bits.hdw.num_ptr,
+ save_desc_p->bits.hdw.mark,
+ save_desc_p->bits.hdw.sop));
+
+ npi_txdma_dump_desc_one(npi_desc_handle, NULL, i);
+#endif
+
+ tx_msg_p->tx_msg_size = clen;
+ i = TXDMA_DESC_NEXT_INDEX(i, 1, tx_ring_p->tx_wrap_mask);
+ if (ngathers > nxge_tx_max_gathers) {
+ good_packet = B_FALSE;
+ hcksum_retrieve(mp, NULL, NULL, &start_offset,
+ &stuff_offset, &end_offset, &value,
+ &cksum_flags);
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_start(14): pull msg - "
+ "len %d pkt_len %d ngathers %d",
+ len, pkt_len, ngathers));
+ /* Pull all message blocks from b_cont */
+ if ((msgpullup(mp, -1)) == NULL) {
+ goto nxge_start_fail2;
+ }
+ goto nxge_start_fail2;
+ }
+ } /* while (nmp) */
+
+ tx_msg_p->tx_message = mp;
+ tx_desc_p = &tx_desc_ring_vp[sop_index];
+ npi_desc_handle.regp = (uint64_t)tx_desc_p;
+
+ pkthdrp = (p_tx_pkt_hdr_all_t)hdrp;
+ pkthdrp->reserved = 0;
+ hdrp->value = 0;
+ (void) nxge_fill_tx_hdr(mp, B_FALSE, cksum_on,
+ (pkt_len - TX_PKT_HEADER_SIZE), npads, pkthdrp);
+
+ if (pkt_len > NXGE_MTU_DEFAULT_MAX) {
+ tdc_stats->tx_jumbo_pkts++;
+ }
+
+ min_len = (nxgep->msg_min + TX_PKT_HEADER_SIZE + (npads * 2));
+ if (pkt_len < min_len) {
+ /* Assume we use bcopy to premapped buffers */
+ kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma);
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_start(14-1): < (msg_min + 16)"
+ "len %d pkt_len %d min_len %d bzero %d ngathers %d",
+ len, pkt_len, min_len, (min_len - pkt_len), ngathers));
+ bzero((kaddr + pkt_len), (min_len - pkt_len));
+ pkt_len = tx_msg_p->tx_msg_size = min_len;
+
+ sop_tx_desc_p->bits.hdw.tr_len = min_len;
+
+ NXGE_MEM_PIO_WRITE64(npi_desc_handle, sop_tx_desc_p->value);
+ tx_desc_p->value = sop_tx_desc_p->value;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_start(14-2): < msg_min - "
+ "len %d pkt_len %d min_len %d ngathers %d",
+ len, pkt_len, min_len, ngathers));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: cksum_flags 0x%x ",
+ cksum_flags));
+ if (cksum_flags & HCK_PARTIALCKSUM) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: cksum_flags 0x%x (partial checksum) ",
+ cksum_flags));
+ cksum_on = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: from IP cksum_flags 0x%x "
+ "(partial checksum) "
+ "start_offset %d stuff_offset %d",
+ cksum_flags, start_offset, stuff_offset));
+ tmp_len = (uint64_t)(start_offset >> 1);
+ hdrp->value |= (tmp_len << TX_PKT_HEADER_L4START_SHIFT);
+ tmp_len = (uint64_t)(stuff_offset >> 1);
+ hdrp->value |= (tmp_len << TX_PKT_HEADER_L4STUFF_SHIFT);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: from IP cksum_flags 0x%x "
+ "(partial checksum) "
+ "after SHIFT start_offset %d stuff_offset %d",
+ cksum_flags, start_offset, stuff_offset));
+ }
+ {
+ uint64_t tmp_len;
+
+ /* pkt_len already includes 16 + paddings!! */
+ /* Update the control header length */
+ tot_xfer_len = (pkt_len - TX_PKT_HEADER_SIZE);
+ tmp_len = hdrp->value |
+ (tot_xfer_len << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(15_x1): setting SOP "
+ "tot_xfer_len 0x%llx (%d) pkt_len %d tmp_len "
+ "0x%llx hdrp->value 0x%llx",
+ tot_xfer_len, tot_xfer_len, pkt_len,
+ tmp_len, hdrp->value));
+#if defined(_BIG_ENDIAN)
+ hdrp->value = ddi_swap64(tmp_len);
+#else
+ hdrp->value = tmp_len;
+#endif
+ NXGE_DEBUG_MSG((nxgep,
+ TX_CTL, "==> nxge_start(15_x2): setting SOP "
+ "after SWAP: tot_xfer_len 0x%llx pkt_len %d "
+ "tmp_len 0x%llx hdrp->value 0x%llx",
+ tot_xfer_len, pkt_len,
+ tmp_len, hdrp->value));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(15): setting SOP "
+ "wr_index %d "
+ "tot_xfer_len (%d) pkt_len %d npads %d",
+ sop_index,
+ tot_xfer_len, pkt_len,
+ npads));
+
+ sop_tx_desc_p->bits.hdw.sop = 1;
+ sop_tx_desc_p->bits.hdw.mark = mark_mode;
+ sop_tx_desc_p->bits.hdw.num_ptr = ngathers;
+
+ NXGE_MEM_PIO_WRITE64(npi_desc_handle, sop_tx_desc_p->value);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start(16): set SOP done"));
+
+#ifdef NXGE_DEBUG
+ npi_desc_handle.nxgep = nxgep;
+ npi_desc_handle.function.function = nxgep->function_num;
+ npi_desc_handle.function.instance = nxgep->instance;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\t: value 0x%llx\n"
+ "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n",
+ save_desc_p->value,
+ sad,
+ save_desc_p->bits.hdw.tr_len,
+ xfer_len,
+ save_desc_p->bits.hdw.num_ptr,
+ save_desc_p->bits.hdw.mark,
+ save_desc_p->bits.hdw.sop));
+ (void) npi_txdma_dump_desc_one(npi_desc_handle, NULL, sop_index);
+
+ dump_len = (pkt_len > 128) ? 128: pkt_len;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start: dump packets(17) (after sop set, len "
+ " (len/dump_len/pkt_len/tot_xfer_len) %d/%d/%d/%d):\n"
+ "ptr $%p: %s", len, dump_len, pkt_len, tot_xfer_len,
+ (char *)hdrp,
+ nxge_dump_packet((char *)hdrp, dump_len)));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_start(18): TX desc sync: sop_index %d",
+ sop_index));
+#endif
+
+ if ((ngathers == 1) || tx_ring_p->wr_index < i) {
+ (void) ddi_dma_sync(tx_desc_dma_handle,
+ sop_index * sizeof (tx_desc_t),
+ ngathers * sizeof (tx_desc_t),
+ DDI_DMA_SYNC_FORDEV);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "nxge_start(19): sync 1 "
+ "cs_off = 0x%02X cs_s_off = 0x%02X "
+ "pkt_len %d ngathers %d sop_index %d\n",
+ stuff_offset, start_offset,
+ pkt_len, ngathers, sop_index));
+ } else { /* more than one descriptor and wrap around */
+ uint32_t nsdescs = tx_ring_p->tx_ring_size - sop_index;
+ (void) ddi_dma_sync(tx_desc_dma_handle,
+ sop_index * sizeof (tx_desc_t),
+ nsdescs * sizeof (tx_desc_t),
+ DDI_DMA_SYNC_FORDEV);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "nxge_start(20): sync 1 "
+ "cs_off = 0x%02X cs_s_off = 0x%02X "
+ "pkt_len %d ngathers %d sop_index %d\n",
+ stuff_offset, start_offset,
+ pkt_len, ngathers, sop_index));
+
+ (void) ddi_dma_sync(tx_desc_dma_handle,
+ 0,
+ (ngathers - nsdescs) * sizeof (tx_desc_t),
+ DDI_DMA_SYNC_FORDEV);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "nxge_start(21): sync 2 "
+ "cs_off = 0x%02X cs_s_off = 0x%02X "
+ "pkt_len %d ngathers %d sop_index %d\n",
+ stuff_offset, start_offset,
+ pkt_len, ngathers, sop_index));
+ }
+
+ tail_index = tx_ring_p->wr_index;
+ tail_wrap = tx_ring_p->wr_index_wrap;
+
+ tx_ring_p->wr_index = i;
+ if (tx_ring_p->wr_index <= tail_index) {
+ tx_ring_p->wr_index_wrap = ((tail_wrap == B_TRUE) ?
+ B_FALSE : B_TRUE);
+ }
+
+ tx_ring_p->descs_pending += ngathers;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: TX kick: "
+ "channel %d wr_index %d wrap %d ngathers %d desc_pend %d",
+ tx_ring_p->tdc,
+ tx_ring_p->wr_index,
+ tx_ring_p->wr_index_wrap,
+ ngathers,
+ tx_ring_p->descs_pending));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: TX KICKING: "));
+
+ {
+ tx_ring_kick_t kick;
+
+ kick.value = 0;
+ kick.bits.ldw.wrap = tx_ring_p->wr_index_wrap;
+ kick.bits.ldw.tail = (uint16_t)tx_ring_p->wr_index;
+
+ /* Kick start the Transmit kick register */
+ TXDMA_REG_WRITE64(NXGE_DEV_NPI_HANDLE(nxgep),
+ TX_RING_KICK_REG,
+ (uint8_t)tx_ring_p->tdc,
+ kick.value);
+ }
+
+ tdc_stats->tx_starts++;
+
+ MUTEX_EXIT(&tx_ring_p->lock);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_start"));
+
+ return (status);
+
+nxge_start_fail2:
+ if (good_packet == B_FALSE) {
+ cur_index = sop_index;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_start: clean up"));
+ for (i = 0; i < ngathers; i++) {
+ tx_desc_p = &tx_desc_ring_vp[cur_index];
+ npi_handle.regp = (uint64_t)tx_desc_p;
+ tx_msg_p = &tx_msg_ring[cur_index];
+ (void) npi_txdma_desc_set_zero(npi_handle, 1);
+ if (tx_msg_p->flags.dma_type == USE_DVMA) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "tx_desc_p = %X index = %d",
+ tx_desc_p, tx_ring_p->rd_index));
+ (void) dvma_unload(
+ tx_msg_p->dvma_handle,
+ 0, -1);
+ tx_msg_p->dvma_handle = NULL;
+ if (tx_ring_p->dvma_wr_index ==
+ tx_ring_p->dvma_wrap_mask)
+ tx_ring_p->dvma_wr_index = 0;
+ else
+ tx_ring_p->dvma_wr_index++;
+ tx_ring_p->dvma_pending--;
+ } else if (tx_msg_p->flags.dma_type ==
+ USE_DMA) {
+ if (ddi_dma_unbind_handle(
+ tx_msg_p->dma_handle))
+ cmn_err(CE_WARN, "!nxge_start: "
+ "ddi_dma_unbind_handle failed");
+ }
+ tx_msg_p->flags.dma_type = USE_NONE;
+ cur_index = TXDMA_DESC_NEXT_INDEX(cur_index, 1,
+ tx_ring_p->tx_wrap_mask);
+
+ }
+
+ nxgep->resched_needed = B_TRUE;
+ }
+
+ MUTEX_EXIT(&tx_ring_p->lock);
+
+nxge_start_fail1:
+ /* Add FMA to check the access handle nxge_hregh */
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_start"));
+
+ return (status);
+}
+
+boolean_t
+nxge_send(p_nxge_t nxgep, mblk_t *mp, p_mac_tx_hint_t hp)
+{
+ p_tx_ring_t *tx_rings;
+ uint8_t ring_index;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_send"));
+
+ ASSERT(mp->b_next == NULL);
+
+ ring_index = nxge_tx_lb_ring_1(mp, nxgep->max_tdcs, hp);
+ tx_rings = nxgep->tx_rings->rings;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_msg: tx_rings $%p",
+ tx_rings));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_msg: max_tdcs %d "
+ "ring_index %d", nxgep->max_tdcs, ring_index));
+
+ if (nxge_start(nxgep, tx_rings[ring_index], mp)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_send: failed "
+ "ring index %d", ring_index));
+ return (B_FALSE);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_send: ring index %d",
+ ring_index));
+
+ return (B_TRUE);
+}
+
+
+/*
+ * nxge_m_tx() - send a chain of packets
+ */
+mblk_t *
+nxge_m_tx(void *arg, mblk_t *mp)
+{
+ p_nxge_t nxgep = (p_nxge_t)arg;
+ mblk_t *next;
+ mac_tx_hint_t hint;
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "==> nxge_m_tx: hardware not initialized"));
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "<== nxge_m_tx"));
+ return (mp);
+ }
+
+ hint.hash = NULL;
+ hint.vid = 0;
+ hint.sap = 0;
+
+ while (mp != NULL) {
+ next = mp->b_next;
+ mp->b_next = NULL;
+
+ /*
+ * Until Nemo tx resource works, the mac driver
+ * does the load balancing based on TCP port,
+ * or CPU. For debugging, we use a system
+ * configurable parameter.
+ */
+ if (!nxge_send(nxgep, mp, &hint)) {
+ mp->b_next = next;
+ break;
+ }
+
+ mp = next;
+ }
+
+ return (mp);
+}
+
+int
+nxge_tx_lb_ring_1(p_mblk_t mp, uint32_t maxtdcs, p_mac_tx_hint_t hp)
+{
+ uint8_t ring_index = 0;
+ uint8_t *tcp_port;
+ p_mblk_t nmp;
+ size_t mblk_len;
+ size_t iph_len;
+ size_t hdrs_size;
+ uint8_t hdrs_buf[sizeof (struct ether_header) +
+ IP_MAX_HDR_LENGTH + sizeof (uint32_t)];
+ /*
+ * allocate space big enough to cover
+ * the max ip header length and the first
+ * 4 bytes of the TCP/IP header.
+ */
+
+ boolean_t qos = B_FALSE;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_lb_ring"));
+
+ if (hp->vid) {
+ qos = B_TRUE;
+ }
+ switch (nxge_tx_lb_policy) {
+ case NXGE_TX_LB_TCPUDP: /* default IPv4 TCP/UDP */
+ default:
+ tcp_port = mp->b_rptr;
+ if (!nxge_no_tx_lb && !qos &&
+ (ntohs(((p_ether_header_t)tcp_port)->ether_type)
+ == ETHERTYPE_IP)) {
+ nmp = mp;
+ mblk_len = MBLKL(nmp);
+ tcp_port = NULL;
+ if (mblk_len > sizeof (struct ether_header) +
+ sizeof (uint8_t)) {
+ tcp_port = nmp->b_rptr +
+ sizeof (struct ether_header);
+ mblk_len -= sizeof (struct ether_header);
+ iph_len = ((*tcp_port) & 0x0f) << 2;
+ if (mblk_len > (iph_len + sizeof (uint32_t))) {
+ tcp_port = nmp->b_rptr;
+ } else {
+ tcp_port = NULL;
+ }
+ }
+ if (tcp_port == NULL) {
+ hdrs_size = 0;
+ ((p_ether_header_t)hdrs_buf)->ether_type = 0;
+ while ((nmp) && (hdrs_size <
+ sizeof (hdrs_buf))) {
+ mblk_len = MBLKL(nmp);
+ if (mblk_len >=
+ (sizeof (hdrs_buf) - hdrs_size))
+ mblk_len = sizeof (hdrs_buf) -
+ hdrs_size;
+ bcopy(nmp->b_rptr,
+ &hdrs_buf[hdrs_size], mblk_len);
+ hdrs_size += mblk_len;
+ nmp = nmp->b_cont;
+ }
+ tcp_port = hdrs_buf;
+ }
+ tcp_port += sizeof (ether_header_t);
+ if (!(tcp_port[6] & 0x3f) && !(tcp_port[7] & 0xff)) {
+ if ((tcp_port[9] == IPPROTO_TCP) ||
+ (tcp_port[9] == IPPROTO_UDP)) {
+ tcp_port += ((*tcp_port) & 0x0f) << 2;
+ ring_index =
+ ((tcp_port[1] ^ tcp_port[3])
+ % maxtdcs);
+ } else {
+ ring_index = tcp_port[19] % maxtdcs;
+ }
+ } else { /* fragmented packet */
+ ring_index = tcp_port[19] % maxtdcs;
+ }
+ } else {
+ ring_index = mp->b_band % maxtdcs;
+ }
+ break;
+
+ case NXGE_TX_LB_HASH:
+ if (hp->hash) {
+ ring_index = ((uint64_t)(hp->hash) % maxtdcs);
+ } else {
+ ring_index = mp->b_band % maxtdcs;
+ }
+ break;
+
+ case NXGE_TX_LB_DEST_MAC: /* Use destination MAC address */
+ tcp_port = mp->b_rptr;
+ ring_index = tcp_port[5] % maxtdcs;
+ break;
+ }
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_tx_lb_ring"));
+
+ return (ring_index);
+}
+
+uint_t
+nxge_reschedule(caddr_t arg)
+{
+ p_nxge_t nxgep;
+
+ nxgep = (p_nxge_t)arg;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reschedule"));
+
+ if (nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
+ nxgep->resched_needed) {
+ mac_tx_update(nxgep->mach);
+ nxgep->resched_needed = B_FALSE;
+ nxgep->resched_running = B_FALSE;
+ }
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_reschedule"));
+ return (DDI_INTR_CLAIMED);
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_txc.c b/usr/src/uts/sun4v/io/nxge/nxge_txc.c
new file mode 100644
index 0000000000..a7f3c24f58
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_txc.c
@@ -0,0 +1,420 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/nxge/nxge_txc.h>
+
+static nxge_status_t
+nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
+static void
+nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
+ uint8_t istats);
+extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
+
+
+nxge_status_t
+nxge_txc_init(p_nxge_t nxgep)
+{
+ uint8_t port;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ port = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
+
+ /*
+ * Enable the TXC controller.
+ */
+ if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* Enable this port within the TXC. */
+ if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* Bind DMA channels to this port. */
+ if ((rs = npi_txc_port_dma_enable(handle, port,
+ TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* Unmask all TXC interrupts */
+ npi_txc_global_imask_set(handle, port, 0);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_init: Failed to initialize txc on port %d",
+ port));
+
+ return (NXGE_ERROR | rs);
+}
+
+nxge_status_t
+nxge_txc_uninit(p_nxge_t nxgep)
+{
+ uint8_t port;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ port = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
+
+ /*
+ * disable the TXC controller.
+ */
+ if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* disable this port within the TXC. */
+ if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ /* unbind DMA channels to this port. */
+ if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_init: Failed to initialize txc on port %d",
+ port));
+
+ return (NXGE_ERROR | rs);
+}
+
+void
+nxge_txc_regs_dump(p_nxge_t nxgep)
+{
+ uint32_t cnt1, cnt2;
+ npi_handle_t handle;
+ txc_control_t control;
+ uint32_t bitmap = 0;
+
+ printf("\nTXC dump: func # %d:\n",
+ nxgep->function_num);
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+
+ (void) npi_txc_control(handle, OP_GET, &control);
+ (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
+
+ printf("\n\tTXC port control 0x%0llx",
+ (long long)control.value);
+ printf("\n\tTXC port bitmap 0x%x", bitmap);
+
+ (void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
+ &cnt1, &cnt2);
+ printf("\n\tTXC bytes to MAC %d packets to MAC %d",
+ cnt1, cnt2);
+
+ (void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
+ &cnt1, &cnt2);
+ printf("\n\tTXC ass packets %d reorder packets %d",
+ cnt1 & 0xffff, cnt2 & 0xffff);
+
+ (void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
+ printf("\n\tTXC reorder resource %d", cnt1 & 0xff);
+}
+
+nxge_status_t
+nxge_txc_handle_sys_errors(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ txc_int_stat_t istatus;
+ uint32_t err_status;
+ uint8_t err_portn;
+ boolean_t my_err = B_FALSE;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+ npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
+ switch (nxgep->mac.portnum) {
+ case 0:
+ if (istatus.bits.ldw.port0_int_status) {
+ my_err = B_TRUE;
+ err_portn = 0;
+ err_status = istatus.bits.ldw.port0_int_status;
+ }
+ break;
+ case 1:
+ if (istatus.bits.ldw.port1_int_status) {
+ my_err = B_TRUE;
+ err_portn = 1;
+ err_status = istatus.bits.ldw.port1_int_status;
+ }
+ break;
+ case 2:
+ if (istatus.bits.ldw.port2_int_status) {
+ my_err = B_TRUE;
+ err_portn = 2;
+ err_status = istatus.bits.ldw.port2_int_status;
+ }
+ break;
+ case 3:
+ if (istatus.bits.ldw.port3_int_status) {
+ my_err = B_TRUE;
+ err_portn = 3;
+ err_status = istatus.bits.ldw.port3_int_status;
+ }
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_txc_handle_sys_erors: errored port %d",
+ err_portn));
+ if (my_err) {
+ status = nxge_txc_handle_port_errors(nxgep, err_status);
+ }
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_txc_stats_t statsp;
+ txc_int_stat_t istatus;
+ boolean_t txport_fatal = B_FALSE;
+ uint8_t portn;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+ statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
+ portn = nxgep->mac.portnum;
+ istatus.value = 0;
+
+ if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
+ (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
+ (err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
+ (err_status & TXC_INT_STAT_REORDER_ERR)) {
+ if ((rs = npi_txc_ro_states_get(handle, portn,
+ &statsp->errlog.ro_st)) != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
+ statsp->ro_correct_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_err_evnts: "
+ "RO FIFO correctable error"));
+ }
+ if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
+ statsp->ro_uncorrect_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_err_evnts: "
+ "RO FIFO uncorrectable error"));
+ }
+ if (err_status & TXC_INT_STAT_REORDER_ERR) {
+ statsp->reorder_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXC_REORDER_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_err_evnts: "
+ "fatal error: Reorder error"));
+ txport_fatal = B_TRUE;
+ }
+
+ if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
+ (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
+ (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
+
+ if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
+ != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ /*
+ * Making sure that error source is cleared if this is
+ * an injected error.
+ */
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
+ portn, 0);
+ }
+ }
+
+ if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
+ (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
+ if ((rs = npi_txc_sf_states_get(handle, portn,
+ &statsp->errlog.sf_st)) != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+ if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
+ statsp->sf_correct_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_err_evnts: "
+ "SF FIFO correctable error"));
+ }
+ if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
+ statsp->sf_uncorrect_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_err_evnts: "
+ "SF FIFO uncorrectable error"));
+ }
+ if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
+ != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ /*
+ * Making sure that error source is cleared if this is
+ * an injected error.
+ */
+ TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
+ }
+
+ /* Clear corresponding errors */
+ switch (portn) {
+ case 0:
+ istatus.bits.ldw.port0_int_status = err_status;
+ break;
+ case 1:
+ istatus.bits.ldw.port1_int_status = err_status;
+ break;
+ case 2:
+ istatus.bits.ldw.port2_int_status = err_status;
+ break;
+ case 3:
+ istatus.bits.ldw.port3_int_status = err_status;
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+
+ npi_txc_global_istatus_clear(handle, istatus.value);
+
+ if (txport_fatal) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_txc_handle_sys_errors:"
+ " fatal Error on Port#%d\n",
+ portn));
+ status = nxge_tx_port_fatal_err_recover(nxgep);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ return (status);
+}
+
+void
+nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
+{
+ txc_int_stat_dbg_t txcs;
+ txc_roecc_ctl_t ro_ecc_ctl;
+ txc_sfecc_ctl_t sf_ecc_ctl;
+ uint8_t portn = nxgep->mac.portnum;
+
+ cmn_err(CE_NOTE, "!TXC error Inject\n");
+ switch (err_id) {
+ case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
+ case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
+ ro_ecc_ctl.value = 0;
+ ro_ecc_ctl.bits.ldw.all_pkts = 1;
+ ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
+ if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
+ ro_ecc_ctl.bits.ldw.single_bit_err = 1;
+ else
+ ro_ecc_ctl.bits.ldw.double_bit_err = 1;
+ cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
+ ro_ecc_ctl.value);
+ TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
+ portn, ro_ecc_ctl.value);
+ break;
+ case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
+ case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
+ sf_ecc_ctl.value = 0;
+ sf_ecc_ctl.bits.ldw.all_pkts = 1;
+ sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
+ if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
+ sf_ecc_ctl.bits.ldw.single_bit_err = 1;
+ else
+ sf_ecc_ctl.bits.ldw.double_bit_err = 1;
+ cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
+ sf_ecc_ctl.value);
+ TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
+ portn, sf_ecc_ctl.value);
+ break;
+ case NXGE_FM_EREPORT_TXC_REORDER_ERR:
+ NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
+ &txcs.value);
+ nxge_txc_inject_port_err(portn, &txcs,
+ TXC_INT_STAT_REORDER_ERR);
+ cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
+ txcs.value);
+ NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
+ txcs.value);
+ break;
+ default:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_txc_inject_err: Unknown err_id"));
+ }
+}
+
+static void
+nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
+ uint8_t istats)
+{
+ switch (portn) {
+ case 0:
+ txcs->bits.ldw.port0_int_status |= istats;
+ break;
+ case 1:
+ txcs->bits.ldw.port1_int_status |= istats;
+ break;
+ case 2:
+ txcs->bits.ldw.port2_int_status |= istats;
+ break;
+ case 3:
+ txcs->bits.ldw.port3_int_status |= istats;
+ break;
+ default:
+ ;
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_txdma.c b/usr/src/uts/sun4v/io/nxge/nxge_txdma.c
new file mode 100644
index 0000000000..3449ad93ea
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_txdma.c
@@ -0,0 +1,3268 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/nxge/nxge_txdma.h>
+#include <sys/llc1.h>
+
+uint32_t nxge_reclaim_pending = TXDMA_RECLAIM_PENDING_DEFAULT;
+uint32_t nxge_tx_minfree = 32;
+uint32_t nxge_tx_intr_thres = 0;
+uint32_t nxge_tx_max_gathers = TX_MAX_GATHER_POINTERS;
+uint32_t nxge_tx_tiny_pack = 1;
+uint32_t nxge_tx_use_bcopy = 1;
+
+extern uint32_t nxge_tx_ring_size;
+extern uint32_t nxge_bcopy_thresh;
+extern uint32_t nxge_dvma_thresh;
+extern uint32_t nxge_dma_stream_thresh;
+extern dma_method_t nxge_force_dma;
+
+/* Device register access attributes for PIO. */
+extern ddi_device_acc_attr_t nxge_dev_reg_acc_attr;
+/* Device descriptor access attributes for DMA. */
+extern ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr;
+/* Device buffer access attributes for DMA. */
+extern ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr;
+extern ddi_dma_attr_t nxge_desc_dma_attr;
+extern ddi_dma_attr_t nxge_tx_dma_attr;
+
+static nxge_status_t nxge_map_txdma(p_nxge_t);
+static void nxge_unmap_txdma(p_nxge_t);
+
+static nxge_status_t nxge_txdma_hw_start(p_nxge_t);
+static void nxge_txdma_hw_stop(p_nxge_t);
+
+static nxge_status_t nxge_map_txdma_channel(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, p_tx_ring_t *,
+ uint32_t, p_nxge_dma_common_t *,
+ p_tx_mbox_t *);
+static void nxge_unmap_txdma_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+
+static nxge_status_t nxge_map_txdma_channel_buf_ring(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, p_tx_ring_t *, uint32_t);
+static void nxge_unmap_txdma_channel_buf_ring(p_nxge_t, p_tx_ring_t);
+
+static void nxge_map_txdma_channel_cfg_ring(p_nxge_t, uint16_t,
+ p_nxge_dma_common_t *, p_tx_ring_t,
+ p_tx_mbox_t *);
+static void nxge_unmap_txdma_channel_cfg_ring(p_nxge_t,
+ p_tx_ring_t, p_tx_mbox_t);
+
+static nxge_status_t nxge_txdma_start_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+static nxge_status_t nxge_txdma_stop_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+
+static p_tx_ring_t nxge_txdma_get_ring(p_nxge_t, uint16_t);
+static nxge_status_t nxge_tx_err_evnts(p_nxge_t, uint_t,
+ p_nxge_ldv_t, tx_cs_t);
+static p_tx_mbox_t nxge_txdma_get_mbox(p_nxge_t, uint16_t);
+static nxge_status_t nxge_txdma_fatal_err_recover(p_nxge_t,
+ uint16_t, p_tx_ring_t);
+
+nxge_status_t
+nxge_init_txdma_channels(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_init_txdma_channels"));
+
+ status = nxge_map_txdma(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_init_txdma_channels: status 0x%x", status));
+ return (status);
+ }
+
+ status = nxge_txdma_hw_start(nxgep);
+ if (status != NXGE_OK) {
+ nxge_unmap_txdma(nxgep);
+ return (status);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_init_txdma_channels: status 0x%x", status));
+
+ return (NXGE_OK);
+}
+
+void
+nxge_uninit_txdma_channels(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_uninit_txdma_channels"));
+
+ nxge_txdma_hw_stop(nxgep);
+ nxge_unmap_txdma(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_uinit_txdma_channels"));
+}
+
+void
+nxge_setup_dma_common(p_nxge_dma_common_t dest_p, p_nxge_dma_common_t src_p,
+ uint32_t entries, uint32_t size)
+{
+ size_t tsize;
+ *dest_p = *src_p;
+ tsize = size * entries;
+ dest_p->alength = tsize;
+ dest_p->nblocks = entries;
+ dest_p->block_size = size;
+ dest_p->offset += tsize;
+
+ src_p->kaddrp = (caddr_t)dest_p->kaddrp + tsize;
+ src_p->alength -= tsize;
+ src_p->dma_cookie.dmac_laddress += tsize;
+ src_p->dma_cookie.dmac_size -= tsize;
+}
+
+nxge_status_t
+nxge_reset_txdma_channel(p_nxge_t nxgep, uint16_t channel, uint64_t reg_data)
+{
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, " ==> nxge_reset_txdma_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ if ((reg_data & TX_CS_RST_MASK) == TX_CS_RST_MASK) {
+ rs = npi_txdma_channel_reset(handle, channel);
+ } else {
+ rs = npi_txdma_channel_control(handle, TXDMA_RESET,
+ channel);
+ }
+
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ /*
+ * Reset the tail (kick) register to 0.
+ * (Hardware will not reset it. Tx overflow fatal
+ * error if tail is not set to 0 after reset!
+ */
+ TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, " <== nxge_reset_txdma_channel"));
+ return (status);
+}
+
+nxge_status_t
+nxge_init_txdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel,
+ p_tx_dma_ent_msk_t mask_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_init_txdma_channel_event_mask"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_txdma_event_mask(handle, OP_SET, channel, mask_p);
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ return (status);
+}
+
+nxge_status_t
+nxge_init_txdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel,
+ uint64_t reg_data)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_init_txdma_channel_cntl_stat"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_txdma_control_status(handle, OP_SET, channel,
+ (p_tx_cs_t)&reg_data);
+
+ if (rs != NPI_SUCCESS) {
+ status = NXGE_ERROR | rs;
+ }
+
+ return (status);
+}
+
+nxge_status_t
+nxge_enable_txdma_channel(p_nxge_t nxgep,
+ uint16_t channel, p_tx_ring_t tx_desc_p, p_tx_mbox_t mbox_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_enable_txdma_channel"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Use configuration data composed at init time.
+ * Write to hardware the transmit ring configurations.
+ */
+ rs = npi_txdma_ring_config(handle, OP_SET, channel,
+ (uint64_t *)&(tx_desc_p->tx_ring_cfig.value));
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Write to hardware the mailbox */
+ rs = npi_txdma_mbox_config(handle, OP_SET, channel,
+ (uint64_t *)&mbox_p->tx_mbox.dma_cookie.dmac_laddress);
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ /* Start the DMA engine. */
+ rs = npi_txdma_channel_init_enable(handle, channel);
+
+ if (rs != NPI_SUCCESS) {
+ return (NXGE_ERROR | rs);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_enable_txdma_channel"));
+
+ return (status);
+}
+
+void
+nxge_fill_tx_hdr(p_mblk_t mp, boolean_t fill_len,
+ boolean_t l4_cksum, int pkt_len, uint8_t npads,
+ p_tx_pkt_hdr_all_t pkthdrp)
+{
+ p_tx_pkt_header_t hdrp;
+ p_mblk_t nmp;
+ uint64_t tmp;
+ size_t mblk_len;
+ size_t iph_len;
+ size_t hdrs_size;
+ uint8_t hdrs_buf[sizeof (struct ether_header) +
+ 64 + sizeof (uint32_t)];
+ uint8_t *ip_buf;
+ uint16_t eth_type;
+ uint8_t ipproto;
+ boolean_t is_vlan = B_FALSE;
+ size_t eth_hdr_size;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: mp $%p", mp));
+
+ /*
+ * Caller should zero out the headers first.
+ */
+ hdrp = (p_tx_pkt_header_t)&pkthdrp->pkthdr;
+
+ if (fill_len) {
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_fill_tx_hdr: pkt_len %d "
+ "npads %d", pkt_len, npads));
+ tmp = (uint64_t)pkt_len;
+ hdrp->value |= (tmp << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT);
+ goto fill_tx_header_done;
+ }
+
+ tmp = (uint64_t)npads;
+ hdrp->value |= (tmp << TX_PKT_HEADER_PAD_SHIFT);
+
+ /*
+ * mp is the original data packet (does not include the
+ * Neptune transmit header).
+ */
+ nmp = mp;
+ mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr;
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: "
+ "mp $%p b_rptr $%p len %d",
+ mp, nmp->b_rptr, mblk_len));
+ ip_buf = NULL;
+ bcopy(nmp->b_rptr, &hdrs_buf[0], sizeof (struct ether_vlan_header));
+ eth_type = ntohs(((p_ether_header_t)hdrs_buf)->ether_type);
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> : nxge_fill_tx_hdr: (value 0x%llx) "
+ "ether type 0x%x", eth_type, hdrp->value));
+
+ if (eth_type < ETHERMTU) {
+ tmp = 1ull;
+ hdrp->value |= (tmp << TX_PKT_HEADER_LLC_SHIFT);
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: LLC "
+ "value 0x%llx", hdrp->value));
+ if (*(hdrs_buf + sizeof (struct ether_header))
+ == LLC_SNAP_SAP) {
+ eth_type = ntohs(*((uint16_t *)(hdrs_buf +
+ sizeof (struct ether_header) + 6)));
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_hdr_init: LLC ether type 0x%x",
+ eth_type));
+ } else {
+ goto fill_tx_header_done;
+ }
+ } else if (eth_type == VLAN_ETHERTYPE) {
+ tmp = 1ull;
+ hdrp->value |= (tmp << TX_PKT_HEADER_VLAN__SHIFT);
+
+ eth_type = ntohs(((struct ether_vlan_header *)
+ hdrs_buf)->ether_type);
+ is_vlan = B_TRUE;
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: VLAN "
+ "value 0x%llx", hdrp->value));
+ }
+
+ if (!is_vlan) {
+ eth_hdr_size = sizeof (struct ether_header);
+ } else {
+ eth_hdr_size = sizeof (struct ether_vlan_header);
+ }
+
+ switch (eth_type) {
+ case ETHERTYPE_IP:
+ if (mblk_len > eth_hdr_size + sizeof (uint8_t)) {
+ ip_buf = nmp->b_rptr + eth_hdr_size;
+ mblk_len -= eth_hdr_size;
+ iph_len = ((*ip_buf) & 0x0f);
+ if (mblk_len > (iph_len + sizeof (uint32_t))) {
+ ip_buf = nmp->b_rptr;
+ ip_buf += eth_hdr_size;
+ } else {
+ ip_buf = NULL;
+ }
+
+ }
+ if (ip_buf == NULL) {
+ hdrs_size = 0;
+ ((p_ether_header_t)hdrs_buf)->ether_type = 0;
+ while ((nmp) && (hdrs_size <
+ sizeof (hdrs_buf))) {
+ mblk_len = (size_t)nmp->b_wptr -
+ (size_t)nmp->b_rptr;
+ if (mblk_len >=
+ (sizeof (hdrs_buf) - hdrs_size))
+ mblk_len = sizeof (hdrs_buf) -
+ hdrs_size;
+ bcopy(nmp->b_rptr,
+ &hdrs_buf[hdrs_size], mblk_len);
+ hdrs_size += mblk_len;
+ nmp = nmp->b_cont;
+ }
+ ip_buf = hdrs_buf;
+ ip_buf += eth_hdr_size;
+ iph_len = ((*ip_buf) & 0x0f);
+ }
+
+ ipproto = ip_buf[9];
+
+ tmp = (uint64_t)iph_len;
+ hdrp->value |= (tmp << TX_PKT_HEADER_IHL_SHIFT);
+ tmp = (uint64_t)(eth_hdr_size >> 1);
+ hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT);
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv4 "
+ " iph_len %d l3start %d eth_hdr_size %d proto 0x%x"
+ "tmp 0x%x",
+ iph_len, hdrp->bits.hdw.l3start, eth_hdr_size,
+ ipproto, tmp));
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IP "
+ "value 0x%llx", hdrp->value));
+
+ break;
+
+ case ETHERTYPE_IPV6:
+ hdrs_size = 0;
+ ((p_ether_header_t)hdrs_buf)->ether_type = 0;
+ while ((nmp) && (hdrs_size <
+ sizeof (hdrs_buf))) {
+ mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr;
+ if (mblk_len >=
+ (sizeof (hdrs_buf) - hdrs_size))
+ mblk_len = sizeof (hdrs_buf) -
+ hdrs_size;
+ bcopy(nmp->b_rptr,
+ &hdrs_buf[hdrs_size], mblk_len);
+ hdrs_size += mblk_len;
+ nmp = nmp->b_cont;
+ }
+ ip_buf = hdrs_buf;
+ ip_buf += eth_hdr_size;
+
+ tmp = 1ull;
+ hdrp->value |= (tmp << TX_PKT_HEADER_IP_VER_SHIFT);
+
+ tmp = (eth_hdr_size >> 1);
+ hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT);
+
+ /* byte 6 is the next header protocol */
+ ipproto = ip_buf[6];
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv6 "
+ " iph_len %d l3start %d eth_hdr_size %d proto 0x%x",
+ iph_len, hdrp->bits.hdw.l3start, eth_hdr_size,
+ ipproto));
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IPv6 "
+ "value 0x%llx", hdrp->value));
+
+ break;
+
+ default:
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: non-IP"));
+ goto fill_tx_header_done;
+ }
+
+ switch (ipproto) {
+ case IPPROTO_TCP:
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_fill_tx_hdr: TCP (cksum flag %d)", l4_cksum));
+ if (l4_cksum) {
+ tmp = 1ull;
+ hdrp->value |= (tmp << TX_PKT_HEADER_PKT_TYPE_SHIFT);
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_hdr_init: TCP CKSUM"
+ "value 0x%llx", hdrp->value));
+ }
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: TCP "
+ "value 0x%llx", hdrp->value));
+ break;
+
+ case IPPROTO_UDP:
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: UDP"));
+ if (l4_cksum) {
+ tmp = 0x2ull;
+ hdrp->value |= (tmp << TX_PKT_HEADER_PKT_TYPE_SHIFT);
+ }
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_hdr_init: UDP"
+ "value 0x%llx", hdrp->value));
+ break;
+
+ default:
+ goto fill_tx_header_done;
+ }
+
+fill_tx_header_done:
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_fill_tx_hdr: pkt_len %d "
+ "npads %d value 0x%llx", pkt_len, npads, hdrp->value));
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_fill_tx_hdr"));
+}
+
+/*ARGSUSED*/
+p_mblk_t
+nxge_tx_pkt_header_reserve(p_mblk_t mp, uint8_t *npads)
+{
+ p_mblk_t newmp = NULL;
+
+ if ((newmp = allocb(TX_PKT_HEADER_SIZE, BPRI_MED)) == NULL) {
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "<== nxge_tx_pkt_header_reserve: allocb failed"));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_header_reserve: get new mp"));
+ DB_TYPE(newmp) = M_DATA;
+ newmp->b_rptr = newmp->b_wptr = DB_LIM(newmp);
+ linkb(newmp, mp);
+ newmp->b_rptr -= TX_PKT_HEADER_SIZE;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==>nxge_tx_pkt_header_reserve: "
+ "b_rptr $%p b_wptr $%p",
+ newmp->b_rptr, newmp->b_wptr));
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "<== nxge_tx_pkt_header_reserve: use new mp"));
+
+ return (newmp);
+}
+
+int
+nxge_tx_pkt_nmblocks(p_mblk_t mp, int *tot_xfer_len_p)
+{
+ uint_t nmblks;
+ ssize_t len;
+ uint_t pkt_len;
+ p_mblk_t nmp, bmp, tmp;
+ uint8_t *b_wptr;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: mp $%p rptr $%p wptr $%p "
+ "len %d", mp, mp->b_rptr, mp->b_wptr, MBLKL(mp)));
+
+ nmp = mp;
+ bmp = mp;
+ nmblks = 0;
+ pkt_len = 0;
+ *tot_xfer_len_p = 0;
+
+ while (nmp) {
+ len = MBLKL(nmp);
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: "
+ "len %d pkt_len %d nmblks %d tot_xfer_len %d",
+ len, pkt_len, nmblks,
+ *tot_xfer_len_p));
+
+ if (len <= 0) {
+ bmp = nmp;
+ nmp = nmp->b_cont;
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: "
+ "len (0) pkt_len %d nmblks %d",
+ pkt_len, nmblks));
+ continue;
+ }
+
+ *tot_xfer_len_p += len;
+ NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: "
+ "len %d pkt_len %d nmblks %d tot_xfer_len %d",
+ len, pkt_len, nmblks,
+ *tot_xfer_len_p));
+
+ if (len < nxge_bcopy_thresh) {
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: "
+ "len %d (< thresh) pkt_len %d nmblks %d",
+ len, pkt_len, nmblks));
+ if (pkt_len == 0)
+ nmblks++;
+ pkt_len += len;
+ if (pkt_len >= nxge_bcopy_thresh) {
+ pkt_len = 0;
+ len = 0;
+ nmp = bmp;
+ }
+ } else {
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: "
+ "len %d (> thresh) pkt_len %d nmblks %d",
+ len, pkt_len, nmblks));
+ pkt_len = 0;
+ nmblks++;
+ /*
+ * Hardware limits the transfer length to 4K.
+ * If len is more than 4K, we need to break
+ * it up to at most 2 more blocks.
+ */
+ if (len > TX_MAX_TRANSFER_LENGTH) {
+ uint32_t nsegs;
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: "
+ "len %d pkt_len %d nmblks %d nsegs %d",
+ len, pkt_len, nmblks, nsegs));
+ nsegs = 1;
+ if (len % (TX_MAX_TRANSFER_LENGTH * 2)) {
+ ++nsegs;
+ }
+ do {
+ b_wptr = nmp->b_rptr +
+ TX_MAX_TRANSFER_LENGTH;
+ nmp->b_wptr = b_wptr;
+ if ((tmp = dupb(nmp)) == NULL) {
+ return (0);
+ }
+ tmp->b_rptr = b_wptr;
+ tmp->b_wptr = nmp->b_wptr;
+ tmp->b_cont = nmp->b_cont;
+ nmp->b_cont = tmp;
+ nmblks++;
+ if (--nsegs) {
+ nmp = tmp;
+ }
+ } while (nsegs);
+ nmp = tmp;
+ }
+ }
+
+ /*
+ * Hardware limits the transmit gather pointers to 15.
+ */
+ if (nmp->b_cont && (nmblks + TX_GATHER_POINTERS_THRESHOLD) >
+ TX_MAX_GATHER_POINTERS) {
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "==> nxge_tx_pkt_nmblocks: pull msg - "
+ "len %d pkt_len %d nmblks %d",
+ len, pkt_len, nmblks));
+ /* Pull all message blocks from b_cont */
+ if ((tmp = msgpullup(nmp->b_cont, -1)) == NULL) {
+ return (0);
+ }
+ freemsg(nmp->b_cont);
+ nmp->b_cont = tmp;
+ pkt_len = 0;
+ }
+ bmp = nmp;
+ nmp = nmp->b_cont;
+ }
+
+ NXGE_DEBUG_MSG((NULL, TX_CTL,
+ "<== nxge_tx_pkt_nmblocks: rptr $%p wptr $%p "
+ "nmblks %d len %d tot_xfer_len %d",
+ mp->b_rptr, mp->b_wptr, nmblks,
+ MBLKL(mp), *tot_xfer_len_p));
+
+ return (nmblks);
+}
+
+boolean_t
+nxge_txdma_reclaim(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, int nmblks)
+{
+ boolean_t status = B_TRUE;
+ p_nxge_dma_common_t tx_desc_dma_p;
+ nxge_dma_common_t desc_area;
+ p_tx_desc_t tx_desc_ring_vp;
+ p_tx_desc_t tx_desc_p;
+ p_tx_desc_t tx_desc_pp;
+ tx_desc_t r_tx_desc;
+ p_tx_msg_t tx_msg_ring;
+ p_tx_msg_t tx_msg_p;
+ npi_handle_t handle;
+ tx_ring_hdl_t tx_head;
+ uint32_t pkt_len;
+ uint_t tx_rd_index;
+ uint16_t head_index, tail_index;
+ uint8_t tdc;
+ boolean_t head_wrap, tail_wrap;
+ p_nxge_tx_ring_stats_t tdc_stats;
+ int rc;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_reclaim"));
+
+ status = ((tx_ring_p->descs_pending < nxge_reclaim_pending) &&
+ (nmblks != 0));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: pending %d reclaim %d nmblks %d",
+ tx_ring_p->descs_pending, nxge_reclaim_pending,
+ nmblks));
+ if (!status) {
+ tx_desc_dma_p = &tx_ring_p->tdc_desc;
+ desc_area = tx_ring_p->tdc_desc;
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ tx_desc_ring_vp = tx_desc_dma_p->kaddrp;
+ tx_desc_ring_vp =
+ (p_tx_desc_t)DMA_COMMON_VPTR(desc_area);
+ tx_rd_index = tx_ring_p->rd_index;
+ tx_desc_p = &tx_desc_ring_vp[tx_rd_index];
+ tx_msg_ring = tx_ring_p->tx_msg_ring;
+ tx_msg_p = &tx_msg_ring[tx_rd_index];
+ tdc = tx_ring_p->tdc;
+ tdc_stats = tx_ring_p->tdc_stats;
+ if (tx_ring_p->descs_pending > tdc_stats->tx_max_pend) {
+ tdc_stats->tx_max_pend = tx_ring_p->descs_pending;
+ }
+
+ tail_index = tx_ring_p->wr_index;
+ tail_wrap = tx_ring_p->wr_index_wrap;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: tdc %d tx_rd_index %d "
+ "tail_index %d tail_wrap %d "
+ "tx_desc_p $%p ($%p) ",
+ tdc, tx_rd_index, tail_index, tail_wrap,
+ tx_desc_p, (*(uint64_t *)tx_desc_p)));
+ /*
+ * Read the hardware maintained transmit head
+ * and wrap around bit.
+ */
+ TXDMA_REG_READ64(handle, TX_RING_HDL_REG, tdc, &tx_head.value);
+ head_index = tx_head.bits.ldw.head;
+ head_wrap = tx_head.bits.ldw.wrap;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: "
+ "tx_rd_index %d tail %d tail_wrap %d "
+ "head %d wrap %d",
+ tx_rd_index, tail_index, tail_wrap,
+ head_index, head_wrap));
+
+ if (head_index == tail_index) {
+ if (TXDMA_RING_EMPTY(head_index, head_wrap,
+ tail_index, tail_wrap) &&
+ (head_index == tx_rd_index)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: EMPTY"));
+ return (B_TRUE);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: Checking "
+ "if ring full"));
+ if (TXDMA_RING_FULL(head_index, head_wrap, tail_index,
+ tail_wrap)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: full"));
+ return (B_FALSE);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: tx_rd_index and head_index"));
+
+ tx_desc_pp = &r_tx_desc;
+ while ((tx_rd_index != head_index) &&
+ (tx_ring_p->descs_pending != 0)) {
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: Checking if pending"));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: "
+ "descs_pending %d ",
+ tx_ring_p->descs_pending));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: "
+ "(tx_rd_index %d head_index %d "
+ "(tx_desc_p $%p)",
+ tx_rd_index, head_index,
+ tx_desc_p));
+
+ tx_desc_pp->value = tx_desc_p->value;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: "
+ "(tx_rd_index %d head_index %d "
+ "tx_desc_p $%p (desc value 0x%llx) ",
+ tx_rd_index, head_index,
+ tx_desc_pp, (*(uint64_t *)tx_desc_pp)));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: dump desc:"));
+
+ pkt_len = tx_desc_pp->bits.hdw.tr_len;
+ tdc_stats->obytes += pkt_len;
+ tdc_stats->opackets += tx_desc_pp->bits.hdw.sop;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: pkt_len %d "
+ "tdc channel %d opackets %d",
+ pkt_len,
+ tdc,
+ tdc_stats->opackets));
+
+ if (tx_msg_p->flags.dma_type == USE_DVMA) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "tx_desc_p = $%p "
+ "tx_desc_pp = $%p "
+ "index = %d",
+ tx_desc_p,
+ tx_desc_pp,
+ tx_ring_p->rd_index));
+ (void) dvma_unload(tx_msg_p->dvma_handle,
+ 0, -1);
+ tx_msg_p->dvma_handle = NULL;
+ if (tx_ring_p->dvma_wr_index ==
+ tx_ring_p->dvma_wrap_mask) {
+ tx_ring_p->dvma_wr_index = 0;
+ } else {
+ tx_ring_p->dvma_wr_index++;
+ }
+ tx_ring_p->dvma_pending--;
+ } else if (tx_msg_p->flags.dma_type ==
+ USE_DMA) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: "
+ "USE DMA"));
+ if (rc = ddi_dma_unbind_handle
+ (tx_msg_p->dma_handle)) {
+ cmn_err(CE_WARN, "!nxge_reclaim: "
+ "ddi_dma_unbind_handle "
+ "failed. status %d", rc);
+ }
+ }
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_reclaim: count packets"));
+ /*
+ * count a chained packet only once.
+ */
+ if (tx_msg_p->tx_message != NULL) {
+ freemsg(tx_msg_p->tx_message);
+ tx_msg_p->tx_message = NULL;
+ }
+
+ tx_msg_p->flags.dma_type = USE_NONE;
+ tx_rd_index = tx_ring_p->rd_index;
+ tx_rd_index = (tx_rd_index + 1) &
+ tx_ring_p->tx_wrap_mask;
+ tx_ring_p->rd_index = tx_rd_index;
+ tx_ring_p->descs_pending--;
+ tx_desc_p = &tx_desc_ring_vp[tx_rd_index];
+ tx_msg_p = &tx_msg_ring[tx_rd_index];
+ }
+
+ status = (nmblks <= (tx_ring_p->tx_ring_size -
+ tx_ring_p->descs_pending -
+ TX_FULL_MARK));
+ if (status) {
+ cas32((uint32_t *)&tx_ring_p->queueing, 1, 0);
+ }
+ } else {
+ status = (nmblks <=
+ (tx_ring_p->tx_ring_size -
+ tx_ring_p->descs_pending -
+ TX_FULL_MARK));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_reclaim status = 0x%08x", status));
+
+ return (status);
+}
+
+uint_t
+nxge_tx_intr(void *arg1, void *arg2)
+{
+ p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
+ p_nxge_t nxgep = (p_nxge_t)arg2;
+ p_nxge_ldg_t ldgp;
+ uint8_t channel;
+ uint32_t vindex;
+ npi_handle_t handle;
+ tx_cs_t cs;
+ p_tx_ring_t *tx_rings;
+ p_tx_ring_t tx_ring_p;
+ npi_status_t rs = NPI_SUCCESS;
+ uint_t serviced = DDI_INTR_UNCLAIMED;
+ nxge_status_t status = NXGE_OK;
+
+ if (ldvp == NULL) {
+ NXGE_DEBUG_MSG((NULL, INT_CTL,
+ "<== nxge_tx_intr: nxgep $%p ldvp $%p",
+ nxgep, ldvp));
+ return (DDI_INTR_UNCLAIMED);
+ }
+
+ if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
+ nxgep = ldvp->nxgep;
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr: nxgep(arg2) $%p ldvp(arg1) $%p",
+ nxgep, ldvp));
+ /*
+ * This interrupt handler is for a specific
+ * transmit dma channel.
+ */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /* Get the control and status for this channel. */
+ channel = ldvp->channel;
+ ldgp = ldvp->ldgp;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr: nxgep $%p ldvp (ldvp) $%p "
+ "channel %d",
+ nxgep, ldvp, channel));
+
+ rs = npi_txdma_control_status(handle, OP_GET, channel, &cs);
+ vindex = ldvp->vdma_index;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr:channel %d ring index %d status 0x%08x",
+ channel, vindex, rs));
+ if (!rs && cs.bits.ldw.mk) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr:channel %d ring index %d "
+ "status 0x%08x (mk bit set)",
+ channel, vindex, rs));
+ tx_rings = nxgep->tx_rings->rings;
+ tx_ring_p = tx_rings[vindex];
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr:channel %d ring index %d "
+ "status 0x%08x (mk bit set, calling reclaim)",
+ channel, vindex, rs));
+
+ MUTEX_ENTER(&tx_ring_p->lock);
+ (void) nxge_txdma_reclaim(nxgep, tx_rings[vindex], 0);
+ MUTEX_EXIT(&tx_ring_p->lock);
+ mac_tx_update(nxgep->mach);
+ }
+
+ /*
+ * Process other transmit control and status.
+ * Check the ldv state.
+ */
+ status = nxge_tx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs);
+ /*
+ * Rearm this logical group if this is a single device
+ * group.
+ */
+ if (ldgp->nldvs == 1) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_tx_intr: rearm"));
+ if (status == NXGE_OK) {
+ (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ B_TRUE, ldgp->ldg_timer);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_tx_intr"));
+ serviced = DDI_INTR_CLAIMED;
+ return (serviced);
+}
+
+void
+nxge_txdma_stop(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop"));
+
+ (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
+ (void) nxge_tx_mac_disable(nxgep);
+ (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop"));
+}
+
+void
+nxge_txdma_stop_start(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_start"));
+
+ (void) nxge_txdma_stop(nxgep);
+
+ (void) nxge_fixup_txdma_rings(nxgep);
+ (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
+ (void) nxge_tx_mac_enable(nxgep);
+ (void) nxge_txdma_hw_kick(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_start"));
+}
+
+
+nxge_status_t
+nxge_txdma_hw_mode(p_nxge_t nxgep, boolean_t enable)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t *tx_desc_rings;
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: enable mode %d", enable));
+
+ if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_mode: not initialized"));
+ return (NXGE_ERROR);
+ }
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_mode: NULL global ring pointer"));
+ return (NXGE_ERROR);
+ }
+
+ tx_desc_rings = tx_rings->rings;
+ if (tx_desc_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_mode: NULL rings pointer"));
+ return (NXGE_ERROR);
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_txdma_hw_mode: no dma channel allocated"));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_mode: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_desc_rings, ndmas));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ channel = tx_desc_rings[i]->tdc;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: channel %d", channel));
+ if (enable) {
+ rs = npi_txdma_channel_enable(handle, channel);
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: channel %d (enable) "
+ "rs 0x%x", channel, rs));
+ } else {
+ /*
+ * Stop the dma channel and waits for the stop done.
+ * If the stop done bit is not set, then force
+ * an error so TXC will stop.
+ * All channels bound to this port need to be stopped
+ * and reset after injecting an interrupt error.
+ */
+ rs = npi_txdma_channel_disable(handle, channel);
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: channel %d (disable) "
+ "rs 0x%x", channel, rs));
+ {
+ tdmc_intr_dbg_t intr_dbg;
+
+ if (rs != NPI_SUCCESS) {
+ /* Inject any error */
+ intr_dbg.value = 0;
+ intr_dbg.bits.ldw.nack_pref = 1;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: "
+ "channel %d (stop failed 0x%x) "
+ "(inject err)", rs, channel));
+ (void) npi_txdma_inj_int_error_set(
+ handle, channel, &intr_dbg);
+ rs = npi_txdma_channel_disable(handle,
+ channel);
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_mode: "
+ "channel %d (stop again 0x%x) "
+ "(after inject err)",
+ rs, channel));
+ }
+ }
+ }
+ }
+
+ status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_txdma_hw_mode: status 0x%x", status));
+
+ return (status);
+}
+
+void
+nxge_txdma_enable_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_txdma_enable_channel: channel %d", channel));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /* enable the transmit dma channels */
+ (void) npi_txdma_channel_enable(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_txdma_enable_channel"));
+}
+
+void
+nxge_txdma_disable_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, DMA_CTL,
+ "==> nxge_txdma_disable_channel: channel %d", channel));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /* stop the transmit dma channels */
+ (void) npi_txdma_channel_disable(handle, channel);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_disable_channel"));
+}
+
+int
+nxge_txdma_stop_inj_err(p_nxge_t nxgep, int channel)
+{
+ npi_handle_t handle;
+ tdmc_intr_dbg_t intr_dbg;
+ int status;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_inj_err"));
+ /*
+ * Stop the dma channel waits for the stop done.
+ * If the stop done bit is not set, then create
+ * an error.
+ */
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ rs = npi_txdma_channel_disable(handle, channel);
+ status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
+ if (status == NXGE_OK) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_stop_inj_err (channel %d): "
+ "stopped OK", channel));
+ return (status);
+ }
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_stop_inj_err (channel %d): stop failed (0x%x) "
+ "injecting error", channel, rs));
+ /* Inject any error */
+ intr_dbg.value = 0;
+ intr_dbg.bits.ldw.nack_pref = 1;
+ (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg);
+
+ /* Stop done bit will be set as a result of error injection */
+ rs = npi_txdma_channel_disable(handle, channel);
+ status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs);
+ if (!(rs & NPI_TXDMA_STOP_FAILED)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_stop_inj_err (channel %d): "
+ "stopped OK ", channel));
+ return (status);
+ }
+
+#if defined(NXGE_DEBUG)
+ nxge_txdma_regs_dump_channels(nxgep);
+#endif
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_stop_inj_err (channel): stop failed (0x%x) "
+ " (injected error but still not stopped)", channel, rs));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_inj_err"));
+ return (status);
+}
+
+void
+nxge_hw_start_tx(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_start_tx"));
+
+ (void) nxge_txdma_hw_start(nxgep);
+ (void) nxge_tx_mac_enable(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_start_tx"));
+}
+
+/*ARGSUSED*/
+void
+nxge_fixup_txdma_rings(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_txdma_rings"));
+
+ /*
+ * For each transmit channel, reclaim each descriptor and
+ * free buffers.
+ */
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_fixup_txdma_rings: NULL ring pointer"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_fixup_txdma_rings: no channel allocated"));
+ return;
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_fixup_txdma_rings: NULL rings pointer"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_fixup_txdma_rings: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings->rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_fixup_txdma_rings: channel %d", channel));
+
+ nxge_txdma_fixup_channel(nxgep, tx_rings->rings[index],
+ channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_txdma_rings"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_fix_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ p_tx_ring_t ring_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_channel"));
+ ring_p = nxge_txdma_get_ring(nxgep, channel);
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel"));
+ return;
+ }
+
+ if (ring_p->tdc != channel) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fix_channel: channel not matched "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ nxge_txdma_fixup_channel(nxgep, ring_p, channel);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_fixup_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel)
+{
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_channel"));
+
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_channel: NULL ring pointer"));
+ return;
+ }
+
+ if (ring_p->tdc != channel) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_channel: channel not matched "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ MUTEX_ENTER(&ring_p->lock);
+ (void) nxge_txdma_reclaim(nxgep, ring_p, 0);
+ ring_p->rd_index = 0;
+ ring_p->wr_index = 0;
+ ring_p->ring_head.value = 0;
+ ring_p->ring_kick_tail.value = 0;
+ ring_p->descs_pending = 0;
+ MUTEX_EXIT(&ring_p->lock);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_hw_kick(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick"));
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_kick: NULL ring pointer"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_kick: no channel allocated"));
+ return;
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_kick: NULL rings pointer"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_kick: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings->rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_kick: channel %d", channel));
+ nxge_txdma_hw_kick_channel(nxgep, tx_rings->rings[index],
+ channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_kick_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ p_tx_ring_t ring_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_kick_channel"));
+
+ ring_p = nxge_txdma_get_ring(nxgep, channel);
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ " nxge_txdma_kick_channel"));
+ return;
+ }
+
+ if (ring_p->tdc != channel) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_kick_channel: channel not matched "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ nxge_txdma_hw_kick_channel(nxgep, ring_p, channel);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_kick_channel"));
+}
+/*ARGSUSED*/
+void
+nxge_txdma_hw_kick_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel)
+{
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick_channel"));
+
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_kick_channel: NULL ring pointer"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_check_tx_hang(p_nxge_t nxgep)
+{
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_check_tx_hang"));
+
+ /*
+ * Needs inputs from hardware for regs:
+ * head index had not moved since last timeout.
+ * packets not transmitted or stuffed registers.
+ */
+ if (nxge_txdma_hung(nxgep)) {
+ nxge_fixup_hung_txdma_rings(nxgep);
+ }
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_check_tx_hang"));
+}
+
+int
+nxge_txdma_hung(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t tx_ring_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hung"));
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hung: NULL ring pointer"));
+ return (B_FALSE);
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hung: no channel "
+ "allocated"));
+ return (B_FALSE);
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hung: NULL rings pointer"));
+ return (B_FALSE);
+ }
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ tx_ring_p = tx_rings->rings[index];
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_hung: channel %d", channel));
+ if (nxge_txdma_channel_hung(nxgep, tx_ring_p, channel)) {
+ return (B_TRUE);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hung"));
+
+ return (B_FALSE);
+}
+
+int
+nxge_txdma_channel_hung(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, uint16_t channel)
+{
+ uint16_t head_index, tail_index;
+ boolean_t head_wrap, tail_wrap;
+ npi_handle_t handle;
+ tx_ring_hdl_t tx_head;
+ uint_t tx_rd_index;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_channel_hung"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: channel %d", channel));
+ MUTEX_ENTER(&tx_ring_p->lock);
+ (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
+
+ tail_index = tx_ring_p->wr_index;
+ tail_wrap = tx_ring_p->wr_index_wrap;
+ tx_rd_index = tx_ring_p->rd_index;
+ MUTEX_EXIT(&tx_ring_p->lock);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: tdc %d tx_rd_index %d "
+ "tail_index %d tail_wrap %d ",
+ channel, tx_rd_index, tail_index, tail_wrap));
+ /*
+ * Read the hardware maintained transmit head
+ * and wrap around bit.
+ */
+ (void) npi_txdma_ring_head_get(handle, channel, &tx_head);
+ head_index = tx_head.bits.ldw.head;
+ head_wrap = tx_head.bits.ldw.wrap;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: "
+ "tx_rd_index %d tail %d tail_wrap %d "
+ "head %d wrap %d",
+ tx_rd_index, tail_index, tail_wrap,
+ head_index, head_wrap));
+
+ if (TXDMA_RING_EMPTY(head_index, head_wrap,
+ tail_index, tail_wrap) &&
+ (head_index == tx_rd_index)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: EMPTY"));
+ return (B_FALSE);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: Checking if ring full"));
+ if (TXDMA_RING_FULL(head_index, head_wrap, tail_index,
+ tail_wrap)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_channel_hung: full"));
+ return (B_TRUE);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_channel_hung"));
+
+ return (B_FALSE);
+}
+
+/*ARGSUSED*/
+void
+nxge_fixup_hung_txdma_rings(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings"));
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_fixup_hung_txdma_rings: NULL ring pointer"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_fixup_hung_txdma_rings: no channel "
+ "allocated"));
+ return;
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_fixup_hung_txdma_rings: NULL rings pointer"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings->rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_fixup_hung_txdma_rings: channel %d",
+ channel));
+
+ nxge_txdma_fixup_hung_channel(nxgep, tx_rings->rings[index],
+ channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_hung_txdma_rings"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_fix_hung_channel(p_nxge_t nxgep, uint16_t channel)
+{
+ p_tx_ring_t ring_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_hung_channel"));
+ ring_p = nxge_txdma_get_ring(nxgep, channel);
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fix_hung_channel"));
+ return;
+ }
+
+ if (ring_p->tdc != channel) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fix_hung_channel: channel not matched "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ nxge_txdma_fixup_channel(nxgep, ring_p, channel);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_hung_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, p_tx_ring_t ring_p,
+ uint16_t channel)
+{
+ npi_handle_t handle;
+ tdmc_intr_dbg_t intr_dbg;
+ int status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_hung_channel"));
+
+ if (ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_channel: NULL ring pointer"));
+ return;
+ }
+
+ if (ring_p->tdc != channel) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_hung_channel: channel "
+ "not matched "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ /* Reclaim descriptors */
+ MUTEX_ENTER(&ring_p->lock);
+ (void) nxge_txdma_reclaim(nxgep, ring_p, 0);
+ MUTEX_EXIT(&ring_p->lock);
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /*
+ * Stop the dma channel waits for the stop done.
+ * If the stop done bit is not set, then force
+ * an error.
+ */
+ status = npi_txdma_channel_disable(handle, channel);
+ if (!(status & NPI_TXDMA_STOP_FAILED)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_hung_channel: stopped OK "
+ "ring tdc %d passed channel %d",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ /* Inject any error */
+ intr_dbg.value = 0;
+ intr_dbg.bits.ldw.nack_pref = 1;
+ (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg);
+
+ /* Stop done bit will be set as a result of error injection */
+ status = npi_txdma_channel_disable(handle, channel);
+ if (!(status & NPI_TXDMA_STOP_FAILED)) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_hung_channel: stopped again"
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_fixup_hung_channel: stop done still not set!! "
+ "ring tdc %d passed channel",
+ ring_p->tdc, channel));
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_hung_channel"));
+}
+
+/*ARGSUSED*/
+void
+nxge_reclaim_rings(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t tx_ring_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclaim_ring"));
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_reclain_rimgs: NULL ring pointer"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_reclain_rimgs: no channel "
+ "allocated"));
+ return;
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_reclain_rimgs: NULL rings pointer"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclain_rimgs: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings->rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> reclain_rimgs: channel %d",
+ channel));
+ tx_ring_p = tx_rings->rings[index];
+ MUTEX_ENTER(&tx_ring_p->lock);
+ (void) nxge_txdma_reclaim(nxgep, tx_ring_p, channel);
+ MUTEX_EXIT(&tx_ring_p->lock);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_reclaim_rings"));
+}
+
+void
+nxge_txdma_regs_dump_channels(p_nxge_t nxgep)
+{
+ int index, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_txdma_regs_dump_channels"));
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_txdma_dump_fzc_regs(handle);
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_regs_dump_channels: NULL ring"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_regs_dump_channels: "
+ "no channel allocated"));
+ return;
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_regs_dump_channels: NULL rings"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_regs_dump_channels: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings->rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_regs_dump_channels: channel %d",
+ channel));
+ (void) npi_txdma_dump_tdc_regs(handle, channel);
+ }
+
+ /* Dump TXC registers */
+ (void) npi_txc_dump_fzc_regs(handle);
+ (void) npi_txc_dump_port_fzc_regs(handle, nxgep->function_num);
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_regs_dump_channels: channel %d",
+ channel));
+ (void) npi_txc_dump_tdc_fzc_regs(handle, channel);
+ }
+
+ for (index = 0; index < ndmas; index++) {
+ channel = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_txdma_regs_dump_channels: channel %d",
+ channel));
+ nxge_txdma_regs_dump(nxgep, channel);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_regs_dump"));
+
+}
+
+void
+nxge_txdma_regs_dump(p_nxge_t nxgep, int channel)
+{
+ npi_handle_t handle;
+ tx_ring_hdl_t hdl;
+ tx_ring_kick_t kick;
+ tx_cs_t cs;
+ txc_control_t control;
+ uint32_t bitmap = 0;
+ uint32_t burst = 0;
+ uint32_t bytes = 0;
+ dma_log_page_t cfg;
+
+ printf("\n\tfunc # %d tdc %d ",
+ nxgep->function_num, channel);
+ cfg.page_num = 0;
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_txdma_log_page_get(handle, channel, &cfg);
+ printf("\n\tlog page func %d valid page 0 %d",
+ cfg.func_num, cfg.valid);
+ cfg.page_num = 1;
+ (void) npi_txdma_log_page_get(handle, channel, &cfg);
+ printf("\n\tlog page func %d valid page 1 %d",
+ cfg.func_num, cfg.valid);
+
+ (void) npi_txdma_ring_head_get(handle, channel, &hdl);
+ (void) npi_txdma_desc_kick_reg_get(handle, channel, &kick);
+ printf("\n\thead value is 0x%0llx",
+ (long long)hdl.value);
+ printf("\n\thead index %d", hdl.bits.ldw.head);
+ printf("\n\tkick value is 0x%0llx",
+ (long long)kick.value);
+ printf("\n\ttail index %d\n", kick.bits.ldw.tail);
+
+ (void) npi_txdma_control_status(handle, OP_GET, channel, &cs);
+ printf("\n\tControl statue is 0x%0llx", (long long)cs.value);
+ printf("\n\tControl status RST state %d", cs.bits.ldw.rst);
+
+ (void) npi_txc_control(handle, OP_GET, &control);
+ (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
+ (void) npi_txc_dma_max_burst(handle, OP_GET, channel, &burst);
+ (void) npi_txc_dma_bytes_transmitted(handle, channel, &bytes);
+
+ printf("\n\tTXC port control 0x%0llx",
+ (long long)control.value);
+ printf("\n\tTXC port bitmap 0x%x", bitmap);
+ printf("\n\tTXC max burst %d", burst);
+ printf("\n\tTXC bytes xmt %d\n", bytes);
+
+ {
+ ipp_status_t status;
+
+ (void) npi_ipp_get_status(handle, nxgep->function_num, &status);
+ printf("\n\tIPP status 0x%lux\n", (uint64_t)status.value);
+ }
+}
+
+/*
+ * Static functions start here.
+ */
+static nxge_status_t
+nxge_map_txdma(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t *tx_desc_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+ p_tx_mbox_t *tx_mbox_p;
+ p_nxge_dma_pool_t dma_buf_poolp;
+ p_nxge_dma_pool_t dma_cntl_poolp;
+ p_nxge_dma_common_t *dma_buf_p;
+ p_nxge_dma_common_t *dma_cntl_p;
+ nxge_status_t status = NXGE_OK;
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ p_nxge_dma_common_t t_dma_buf_p;
+ p_nxge_dma_common_t t_dma_cntl_p;
+#endif
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma"));
+
+ dma_buf_poolp = nxgep->tx_buf_pool_p;
+ dma_cntl_poolp = nxgep->tx_cntl_pool_p;
+
+ if (!dma_buf_poolp->buf_allocated || !dma_cntl_poolp->buf_allocated) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_map_txdma: buf not allocated"));
+ return (NXGE_ERROR);
+ }
+
+ ndmas = dma_buf_poolp->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_map_txdma: no dma allocated"));
+ return (NXGE_ERROR);
+ }
+
+ dma_buf_p = dma_buf_poolp->dma_buf_pool_p;
+ dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p;
+
+ tx_rings = (p_tx_rings_t)
+ KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP);
+ tx_desc_rings = (p_tx_ring_t *)KMEM_ZALLOC(
+ sizeof (p_tx_ring_t) * ndmas, KM_SLEEP);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: "
+ "tx_rings $%p tx_desc_rings $%p",
+ tx_rings, tx_desc_rings));
+
+ tx_mbox_areas_p = (p_tx_mbox_areas_t)
+ KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP);
+ tx_mbox_p = (p_tx_mbox_t *)KMEM_ZALLOC(
+ sizeof (p_tx_mbox_t) * ndmas, KM_SLEEP);
+
+ /*
+ * Map descriptors from the buffer pools for each dma channel.
+ */
+ for (i = 0; i < ndmas; i++) {
+ /*
+ * Set up and prepare buffer blocks, descriptors
+ * and mailbox.
+ */
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ status = nxge_map_txdma_channel(nxgep, channel,
+ (p_nxge_dma_common_t *)&dma_buf_p[i],
+ (p_tx_ring_t *)&tx_desc_rings[i],
+ dma_buf_poolp->num_chunks[i],
+ (p_nxge_dma_common_t *)&dma_cntl_p[i],
+ (p_tx_mbox_t *)&tx_mbox_p[i]);
+ if (status != NXGE_OK) {
+ goto nxge_map_txdma_fail1;
+ }
+ tx_desc_rings[i]->index = (uint16_t)i;
+ tx_desc_rings[i]->tdc_stats = &nxgep->statsp->tdc_stats[i];
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ if (nxgep->niu_type == N2_NIU && NXGE_DMA_BLOCK == 1) {
+ tx_desc_rings[i]->hv_set = B_FALSE;
+ t_dma_buf_p = (p_nxge_dma_common_t)dma_buf_p[i];
+ t_dma_cntl_p = (p_nxge_dma_common_t)dma_cntl_p[i];
+
+ tx_desc_rings[i]->hv_tx_buf_base_ioaddr_pp =
+ (uint64_t)t_dma_buf_p->orig_ioaddr_pp;
+ tx_desc_rings[i]->hv_tx_buf_ioaddr_size =
+ (uint64_t)t_dma_buf_p->orig_alength;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel: "
+ "hv data buf base io $%p "
+ "size 0x%llx (%d) "
+ "buf base io $%p "
+ "orig vatopa base io $%p "
+ "orig_len 0x%llx (%d)",
+ tx_desc_rings[i]->hv_tx_buf_base_ioaddr_pp,
+ tx_desc_rings[i]->hv_tx_buf_ioaddr_size,
+ tx_desc_rings[i]->hv_tx_buf_ioaddr_size,
+ t_dma_buf_p->ioaddr_pp,
+ t_dma_buf_p->orig_vatopa,
+ t_dma_buf_p->orig_alength,
+ t_dma_buf_p->orig_alength));
+
+ tx_desc_rings[i]->hv_tx_cntl_base_ioaddr_pp =
+ (uint64_t)t_dma_cntl_p->orig_ioaddr_pp;
+ tx_desc_rings[i]->hv_tx_cntl_ioaddr_size =
+ (uint64_t)t_dma_cntl_p->orig_alength;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel: "
+ "hv cntl base io $%p "
+ "orig ioaddr_pp ($%p) "
+ "orig vatopa ($%p) "
+ "size 0x%llx (%d 0x%x)",
+ tx_desc_rings[i]->hv_tx_cntl_base_ioaddr_pp,
+ t_dma_cntl_p->orig_ioaddr_pp,
+ t_dma_cntl_p->orig_vatopa,
+ tx_desc_rings[i]->hv_tx_cntl_ioaddr_size,
+ t_dma_cntl_p->orig_alength,
+ t_dma_cntl_p->orig_alength));
+ }
+#endif
+ }
+
+ tx_rings->ndmas = ndmas;
+ tx_rings->rings = tx_desc_rings;
+ nxgep->tx_rings = tx_rings;
+ tx_mbox_areas_p->txmbox_areas_p = tx_mbox_p;
+ nxgep->tx_mbox_areas_p = tx_mbox_areas_p;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: "
+ "tx_rings $%p rings $%p",
+ nxgep->tx_rings, nxgep->tx_rings->rings));
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: "
+ "tx_rings $%p tx_desc_rings $%p",
+ nxgep->tx_rings, tx_desc_rings));
+
+ goto nxge_map_txdma_exit;
+
+nxge_map_txdma_fail1:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma: uninit tx desc "
+ "(status 0x%x channel %d i %d)",
+ nxgep, status, channel, i));
+ i--;
+ for (; i >= 0; i--) {
+ channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel;
+ nxge_unmap_txdma_channel(nxgep, channel,
+ tx_desc_rings[i],
+ tx_mbox_p[i]);
+ }
+
+ KMEM_FREE(tx_desc_rings, sizeof (p_tx_ring_t) * ndmas);
+ KMEM_FREE(tx_rings, sizeof (tx_rings_t));
+ KMEM_FREE(tx_mbox_p, sizeof (p_tx_mbox_t) * ndmas);
+ KMEM_FREE(tx_mbox_areas_p, sizeof (tx_mbox_areas_t));
+
+nxge_map_txdma_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma: "
+ "(status 0x%x channel %d)",
+ status, channel));
+
+ return (status);
+}
+
+static void
+nxge_unmap_txdma(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint8_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t *tx_desc_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+ p_tx_mbox_t *tx_mbox_p;
+ p_nxge_dma_pool_t dma_buf_poolp;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_unmap_txdma"));
+
+ dma_buf_poolp = nxgep->tx_buf_pool_p;
+ if (!dma_buf_poolp->buf_allocated) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "==> nxge_unmap_txdma: buf not allocated"));
+ return;
+ }
+
+ ndmas = dma_buf_poolp->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_unmap_txdma: no dma allocated"));
+ return;
+ }
+
+ tx_rings = nxgep->tx_rings;
+ tx_desc_rings = tx_rings->rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_unmap_txdma: NULL ring pointer"));
+ return;
+ }
+
+ tx_desc_rings = tx_rings->rings;
+ if (tx_desc_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_unmap_txdma: NULL ring pointers"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_unmap_txdma: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_desc_rings, ndmas));
+
+ tx_mbox_areas_p = nxgep->tx_mbox_areas_p;
+ tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = tx_desc_rings[i]->tdc;
+ (void) nxge_unmap_txdma_channel(nxgep, channel,
+ (p_tx_ring_t)tx_desc_rings[i],
+ (p_tx_mbox_t)tx_mbox_p[i]);
+ }
+
+ KMEM_FREE(tx_desc_rings, sizeof (p_tx_ring_t) * ndmas);
+ KMEM_FREE(tx_rings, sizeof (tx_rings_t));
+ KMEM_FREE(tx_mbox_p, sizeof (p_tx_mbox_t) * ndmas);
+ KMEM_FREE(tx_mbox_areas_p, sizeof (tx_mbox_areas_t));
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_unmap_txdma"));
+}
+
+static nxge_status_t
+nxge_map_txdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_nxge_dma_common_t *dma_buf_p,
+ p_tx_ring_t *tx_desc_p,
+ uint32_t num_chunks,
+ p_nxge_dma_common_t *dma_cntl_p,
+ p_tx_mbox_t *tx_mbox_p)
+{
+ int status = NXGE_OK;
+
+ /*
+ * Set up and prepare buffer blocks, descriptors
+ * and mailbox.
+ */
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel (channel %d)", channel));
+ /*
+ * Transmit buffer blocks
+ */
+ status = nxge_map_txdma_channel_buf_ring(nxgep, channel,
+ dma_buf_p, tx_desc_p, num_chunks);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_map_txdma_channel (channel %d): "
+ "map buffer failed 0x%x", channel, status));
+ goto nxge_map_txdma_channel_exit;
+ }
+
+ /*
+ * Transmit block ring, and mailbox.
+ */
+ nxge_map_txdma_channel_cfg_ring(nxgep, channel, dma_cntl_p, *tx_desc_p,
+ tx_mbox_p);
+
+ goto nxge_map_txdma_channel_exit;
+
+nxge_map_txdma_channel_fail1:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel: unmap buf"
+ "(status 0x%x channel %d)",
+ status, channel));
+ nxge_unmap_txdma_channel_buf_ring(nxgep, *tx_desc_p);
+
+nxge_map_txdma_channel_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_map_txdma_channel: "
+ "(status 0x%x channel %d)",
+ status, channel));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_txdma_channel(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p,
+ p_tx_mbox_t tx_mbox_p)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_unmap_txdma_channel (channel %d)", channel));
+ /*
+ * unmap tx block ring, and mailbox.
+ */
+ (void) nxge_unmap_txdma_channel_cfg_ring(nxgep,
+ tx_ring_p, tx_mbox_p);
+
+ /* unmap buffer blocks */
+ (void) nxge_unmap_txdma_channel_buf_ring(nxgep, tx_ring_p);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_unmap_txdma_channel"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_map_txdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel,
+ p_nxge_dma_common_t *dma_cntl_p,
+ p_tx_ring_t tx_ring_p,
+ p_tx_mbox_t *tx_mbox_p)
+{
+ p_tx_mbox_t mboxp;
+ p_nxge_dma_common_t cntl_dmap;
+ p_nxge_dma_common_t dmap;
+ p_tx_rng_cfig_t tx_ring_cfig_p;
+ p_tx_ring_kick_t tx_ring_kick_p;
+ p_tx_cs_t tx_cs_p;
+ p_tx_dma_ent_msk_t tx_evmask_p;
+ p_txdma_mbh_t mboxh_p;
+ p_txdma_mbl_t mboxl_p;
+ uint64_t tx_desc_len;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring"));
+
+ cntl_dmap = *dma_cntl_p;
+
+ dmap = (p_nxge_dma_common_t)&tx_ring_p->tdc_desc;
+ nxge_setup_dma_common(dmap, cntl_dmap, tx_ring_p->tx_ring_size,
+ sizeof (tx_desc_t));
+ /*
+ * Zero out transmit ring descriptors.
+ */
+ bzero((caddr_t)dmap->kaddrp, dmap->alength);
+ tx_ring_cfig_p = &(tx_ring_p->tx_ring_cfig);
+ tx_ring_kick_p = &(tx_ring_p->tx_ring_kick);
+ tx_cs_p = &(tx_ring_p->tx_cs);
+ tx_evmask_p = &(tx_ring_p->tx_evmask);
+ tx_ring_cfig_p->value = 0;
+ tx_ring_kick_p->value = 0;
+ tx_cs_p->value = 0;
+ tx_evmask_p->value = 0;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring: channel %d des $%p",
+ dma_channel,
+ dmap->dma_cookie.dmac_laddress));
+
+ tx_ring_cfig_p->value = 0;
+ tx_desc_len = (uint64_t)(tx_ring_p->tx_ring_size >> 3);
+ tx_ring_cfig_p->value =
+ (dmap->dma_cookie.dmac_laddress & TX_RNG_CFIG_ADDR_MASK) |
+ (tx_desc_len << TX_RNG_CFIG_LEN_SHIFT);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring: channel %d cfg 0x%llx",
+ dma_channel,
+ tx_ring_cfig_p->value));
+
+ tx_cs_p->bits.ldw.rst = 1;
+
+ /* Map in mailbox */
+ mboxp = (p_tx_mbox_t)
+ KMEM_ZALLOC(sizeof (tx_mbox_t), KM_SLEEP);
+ dmap = (p_nxge_dma_common_t)&mboxp->tx_mbox;
+ nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (txdma_mailbox_t));
+ mboxh_p = (p_txdma_mbh_t)&tx_ring_p->tx_mbox_mbh;
+ mboxl_p = (p_txdma_mbl_t)&tx_ring_p->tx_mbox_mbl;
+ mboxh_p->value = mboxl_p->value = 0;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx",
+ dmap->dma_cookie.dmac_laddress));
+
+ mboxh_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress >>
+ TXDMA_MBH_ADDR_SHIFT) & TXDMA_MBH_MASK);
+
+ mboxl_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress &
+ TXDMA_MBL_MASK) >> TXDMA_MBL_SHIFT);
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx",
+ dmap->dma_cookie.dmac_laddress));
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_cfg_ring: hmbox $%p "
+ "mbox $%p",
+ mboxh_p->bits.ldw.mbaddr, mboxl_p->bits.ldw.mbaddr));
+ tx_ring_p->page_valid.value = 0;
+ tx_ring_p->page_mask_1.value = tx_ring_p->page_mask_2.value = 0;
+ tx_ring_p->page_value_1.value = tx_ring_p->page_value_2.value = 0;
+ tx_ring_p->page_reloc_1.value = tx_ring_p->page_reloc_2.value = 0;
+ tx_ring_p->page_hdl.value = 0;
+
+ tx_ring_p->page_valid.bits.ldw.page0 = 1;
+ tx_ring_p->page_valid.bits.ldw.page1 = 1;
+
+ tx_ring_p->max_burst.value = 0;
+ tx_ring_p->max_burst.bits.ldw.dma_max_burst = TXC_DMA_MAX_BURST_DEFAULT;
+
+ *tx_mbox_p = mboxp;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_map_txdma_channel_cfg_ring"));
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_txdma_channel_cfg_ring(p_nxge_t nxgep,
+ p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p)
+{
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_unmap_txdma_channel_cfg_ring: channel %d",
+ tx_ring_p->tdc));
+
+ KMEM_FREE(tx_mbox_p, sizeof (tx_mbox_t));
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_unmap_txdma_channel_cfg_ring"));
+}
+
+static nxge_status_t
+nxge_map_txdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel,
+ p_nxge_dma_common_t *dma_buf_p,
+ p_tx_ring_t *tx_desc_p, uint32_t num_chunks)
+{
+ p_nxge_dma_common_t dma_bufp, tmp_bufp;
+ p_nxge_dma_common_t dmap;
+ nxge_os_dma_handle_t tx_buf_dma_handle;
+ p_tx_ring_t tx_ring_p;
+ p_tx_msg_t tx_msg_ring;
+ nxge_status_t status = NXGE_OK;
+ int ddi_status = DDI_SUCCESS;
+ int i, j, index;
+ uint32_t size, bsize;
+ uint32_t nblocks, nmsgs;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_buf_ring"));
+
+ dma_bufp = tmp_bufp = *dma_buf_p;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ " nxge_map_txdma_channel_buf_ring: channel %d to map %d "
+ "chunks bufp $%p",
+ channel, num_chunks, dma_bufp));
+
+ nmsgs = 0;
+ for (i = 0; i < num_chunks; i++, tmp_bufp++) {
+ nmsgs += tmp_bufp->nblocks;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_buf_ring: channel %d "
+ "bufp $%p nblocks %d nmsgs %d",
+ channel, tmp_bufp, tmp_bufp->nblocks, nmsgs));
+ }
+ if (!nmsgs) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_map_txdma_channel_buf_ring: channel %d "
+ "no msg blocks",
+ channel));
+ status = NXGE_ERROR;
+ goto nxge_map_txdma_channel_buf_ring_exit;
+ }
+
+ tx_ring_p = (p_tx_ring_t)
+ KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP);
+ MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER,
+ (void *)nxgep->interrupt_cookie);
+ /*
+ * Allocate transmit message rings and handles for packets
+ * not to be copied to premapped buffers.
+ */
+ size = nmsgs * sizeof (tx_msg_t);
+ tx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP);
+ for (i = 0; i < nmsgs; i++) {
+ ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
+ DDI_DMA_DONTWAIT, 0,
+ &tx_msg_ring[i].dma_handle);
+ if (ddi_status != DDI_SUCCESS) {
+ status |= NXGE_DDI_FAILED;
+ break;
+ }
+ }
+ if (i < nmsgs) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "Allocate handles failed."));
+ goto nxge_map_txdma_channel_buf_ring_fail1;
+ }
+
+ tx_ring_p->tdc = channel;
+ tx_ring_p->tx_msg_ring = tx_msg_ring;
+ tx_ring_p->tx_ring_size = nmsgs;
+ tx_ring_p->num_chunks = num_chunks;
+ if (!nxge_tx_intr_thres) {
+ nxge_tx_intr_thres = tx_ring_p->tx_ring_size/4;
+ }
+ tx_ring_p->tx_wrap_mask = tx_ring_p->tx_ring_size - 1;
+ tx_ring_p->rd_index = 0;
+ tx_ring_p->wr_index = 0;
+ tx_ring_p->ring_head.value = 0;
+ tx_ring_p->ring_kick_tail.value = 0;
+ tx_ring_p->descs_pending = 0;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_buf_ring: channel %d "
+ "actual tx desc max %d nmsgs %d "
+ "(config nxge_tx_ring_size %d)",
+ channel, tx_ring_p->tx_ring_size, nmsgs,
+ nxge_tx_ring_size));
+
+ /*
+ * Map in buffers from the buffer pool.
+ */
+ index = 0;
+ bsize = dma_bufp->block_size;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel_buf_ring: "
+ "dma_bufp $%p tx_rng_p $%p "
+ "tx_msg_rng_p $%p bsize %d",
+ dma_bufp, tx_ring_p, tx_msg_ring, bsize));
+
+ tx_buf_dma_handle = dma_bufp->dma_handle;
+ for (i = 0; i < num_chunks; i++, dma_bufp++) {
+ bsize = dma_bufp->block_size;
+ nblocks = dma_bufp->nblocks;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_buf_ring: dma chunk %d "
+ "size %d dma_bufp $%p",
+ i, sizeof (nxge_dma_common_t), dma_bufp));
+
+ for (j = 0; j < nblocks; j++) {
+ tx_msg_ring[index].buf_dma_handle = tx_buf_dma_handle;
+ dmap = &tx_msg_ring[index++].buf_dma;
+#ifdef TX_MEM_DEBUG
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_map_txdma_channel_buf_ring: j %d"
+ "dmap $%p", i, dmap));
+#endif
+ nxge_setup_dma_common(dmap, dma_bufp, 1,
+ bsize);
+ }
+ }
+
+ if (i < num_chunks) {
+ goto nxge_map_txdma_channel_buf_ring_fail1;
+ }
+
+ *tx_desc_p = tx_ring_p;
+
+ goto nxge_map_txdma_channel_buf_ring_exit;
+
+nxge_map_txdma_channel_buf_ring_fail1:
+ index--;
+ for (; index >= 0; index--) {
+ if (tx_msg_ring[i].dma_handle != NULL) {
+ ddi_dma_free_handle(&tx_msg_ring[i].dma_handle);
+ }
+ }
+ MUTEX_DESTROY(&tx_ring_p->lock);
+ KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size);
+ KMEM_FREE(tx_ring_p, sizeof (tx_ring_t));
+
+nxge_map_txdma_channel_buf_ring_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_map_txdma_channel_buf_ring status 0x%x", status));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+nxge_unmap_txdma_channel_buf_ring(p_nxge_t nxgep, p_tx_ring_t tx_ring_p)
+{
+ p_tx_msg_t tx_msg_ring;
+ p_tx_msg_t tx_msg_p;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_unmap_txdma_channel_buf_ring"));
+ if (tx_ring_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_unmap_txdma_channel_buf_ring: NULL ringp"));
+ return;
+ }
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_unmap_txdma_channel_buf_ring: channel %d",
+ tx_ring_p->tdc));
+
+ tx_msg_ring = tx_ring_p->tx_msg_ring;
+ for (i = 0; i < tx_ring_p->tx_ring_size; i++) {
+ tx_msg_p = &tx_msg_ring[i];
+ if (tx_msg_p->flags.dma_type == USE_DVMA) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "entry = %d",
+ i));
+ (void) dvma_unload(tx_msg_p->dvma_handle,
+ 0, -1);
+ tx_msg_p->dvma_handle = NULL;
+ if (tx_ring_p->dvma_wr_index ==
+ tx_ring_p->dvma_wrap_mask) {
+ tx_ring_p->dvma_wr_index = 0;
+ } else {
+ tx_ring_p->dvma_wr_index++;
+ }
+ tx_ring_p->dvma_pending--;
+ } else if (tx_msg_p->flags.dma_type ==
+ USE_DMA) {
+ if (ddi_dma_unbind_handle
+ (tx_msg_p->dma_handle)) {
+ cmn_err(CE_WARN, "!nxge_unmap_tx_bug_ring: "
+ "ddi_dma_unbind_handle "
+ "failed.");
+ }
+ }
+
+ if (tx_msg_p->tx_message != NULL) {
+ freemsg(tx_msg_p->tx_message);
+ tx_msg_p->tx_message = NULL;
+ }
+ }
+
+ for (i = 0; i < tx_ring_p->tx_ring_size; i++) {
+ if (tx_msg_ring[i].dma_handle != NULL) {
+ ddi_dma_free_handle(&tx_msg_ring[i].dma_handle);
+ }
+ }
+
+ MUTEX_DESTROY(&tx_ring_p->lock);
+ KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size);
+ KMEM_FREE(tx_ring_p, sizeof (tx_ring_t));
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_unmap_txdma_channel_buf_ring"));
+}
+
+static nxge_status_t
+nxge_txdma_hw_start(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t *tx_desc_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+ p_tx_mbox_t *tx_mbox_p;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start"));
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_start: NULL ring pointer"));
+ return (NXGE_ERROR);
+ }
+ tx_desc_rings = tx_rings->rings;
+ if (tx_desc_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_start: NULL ring pointers"));
+ return (NXGE_ERROR);
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_start: no dma channel allocated"));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_desc_rings, ndmas));
+
+ tx_mbox_areas_p = nxgep->tx_mbox_areas_p;
+ tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = tx_desc_rings[i]->tdc,
+ status = nxge_txdma_start_channel(nxgep, channel,
+ (p_tx_ring_t)tx_desc_rings[i],
+ (p_tx_mbox_t)tx_mbox_p[i]);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_hw_start_fail1;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
+ "tx_rings $%p rings $%p",
+ nxgep->tx_rings, nxgep->tx_rings->rings));
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: "
+ "tx_rings $%p tx_desc_rings $%p",
+ nxgep->tx_rings, tx_desc_rings));
+
+ goto nxge_txdma_hw_start_exit;
+
+nxge_txdma_hw_start_fail1:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_start: disable "
+ "(status 0x%x channel %d i %d)", status, channel, i));
+ for (; i >= 0; i--) {
+ channel = tx_desc_rings[i]->tdc,
+ (void) nxge_txdma_stop_channel(nxgep, channel,
+ (p_tx_ring_t)tx_desc_rings[i],
+ (p_tx_mbox_t)tx_mbox_p[i]);
+ }
+
+nxge_txdma_hw_start_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_hw_start: (status 0x%x)", status));
+
+ return (status);
+}
+
+static void
+nxge_txdma_hw_stop(p_nxge_t nxgep)
+{
+ int i, ndmas;
+ uint16_t channel;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t *tx_desc_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+ p_tx_mbox_t *tx_mbox_p;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop"));
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_stop: NULL ring pointer"));
+ return;
+ }
+ tx_desc_rings = tx_rings->rings;
+ if (tx_desc_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_stop: NULL ring pointers"));
+ return;
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_hw_stop: no dma channel allocated"));
+ return;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop: "
+ "tx_rings $%p tx_desc_rings $%p",
+ tx_rings, tx_desc_rings));
+
+ tx_mbox_areas_p = nxgep->tx_mbox_areas_p;
+ tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p;
+
+ for (i = 0; i < ndmas; i++) {
+ channel = tx_desc_rings[i]->tdc;
+ (void) nxge_txdma_stop_channel(nxgep, channel,
+ (p_tx_ring_t)tx_desc_rings[i],
+ (p_tx_mbox_t)tx_mbox_p[i]);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop: "
+ "tx_rings $%p tx_desc_rings $%p",
+ tx_rings, tx_desc_rings));
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_hw_stop"));
+}
+
+static nxge_status_t
+nxge_txdma_start_channel(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p)
+
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_start_channel (channel %d)", channel));
+ /*
+ * TXDMA/TXC must be in stopped state.
+ */
+ (void) nxge_txdma_stop_inj_err(nxgep, channel);
+
+ /*
+ * Reset TXDMA channel
+ */
+ tx_ring_p->tx_cs.value = 0;
+ tx_ring_p->tx_cs.bits.ldw.rst = 1;
+ status = nxge_reset_txdma_channel(nxgep, channel,
+ tx_ring_p->tx_cs.value);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_start_channel (channel %d)"
+ " reset channel failed 0x%x", channel, status));
+ goto nxge_txdma_start_channel_exit;
+ }
+
+ /*
+ * Initialize the TXDMA channel specific FZC control
+ * configurations. These FZC registers are pertaining
+ * to each TX channel (i.e. logical pages).
+ */
+ status = nxge_init_fzc_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_start_channel_exit;
+ }
+
+ /*
+ * Initialize the event masks.
+ */
+ tx_ring_p->tx_evmask.value = 0;
+ status = nxge_init_txdma_channel_event_mask(nxgep,
+ channel, &tx_ring_p->tx_evmask);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_start_channel_exit;
+ }
+
+ /*
+ * Load TXDMA descriptors, buffers, mailbox,
+ * initialise the DMA channels and
+ * enable each DMA channel.
+ */
+ status = nxge_enable_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_start_channel_exit;
+ }
+
+nxge_txdma_start_channel_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_start_channel"));
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_txdma_stop_channel(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p)
+{
+ int status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_stop_channel: channel %d", channel));
+
+ /*
+ * Stop (disable) TXDMA and TXC (if stop bit is set
+ * and STOP_N_GO bit not set, the TXDMA reset state will
+ * not be set if reset TXDMA.
+ */
+ (void) nxge_txdma_stop_inj_err(nxgep, channel);
+
+ /*
+ * Reset TXDMA channel
+ */
+ tx_ring_p->tx_cs.value = 0;
+ tx_ring_p->tx_cs.bits.ldw.rst = 1;
+ status = nxge_reset_txdma_channel(nxgep, channel,
+ tx_ring_p->tx_cs.value);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_stop_channel_exit;
+ }
+
+#ifdef HARDWARE_REQUIRED
+ /* Set up the interrupt event masks. */
+ tx_ring_p->tx_evmask.value = 0;
+ status = nxge_init_txdma_channel_event_mask(nxgep,
+ channel, &tx_ring_p->tx_evmask);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_stop_channel_exit;
+ }
+
+ /* Initialize the DMA control and status register */
+ tx_ring_p->tx_cs.value = TX_ENT_MSK_MK_ALL;
+ status = nxge_init_txdma_channel_cntl_stat(nxgep, channel,
+ tx_ring_p->tx_cs.value);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_stop_channel_exit;
+ }
+
+ /* Disable channel */
+ status = nxge_disable_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ if (status != NXGE_OK) {
+ goto nxge_txdma_start_channel_exit;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_stop_channel: event done"));
+
+#endif
+
+nxge_txdma_stop_channel_exit:
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_stop_channel"));
+ return (status);
+}
+
+static p_tx_ring_t
+nxge_txdma_get_ring(p_nxge_t nxgep, uint16_t channel)
+{
+ int index, ndmas;
+ uint16_t tdc;
+ p_tx_rings_t tx_rings;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_ring"));
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_get_ring: NULL ring pointer"));
+ return (NULL);
+ }
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_get_ring: no channel allocated"));
+ return (NULL);
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_get_ring: NULL rings pointer"));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_get_ring: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ tdc = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_fixup_txdma_rings: channel %d", tdc));
+ if (channel == tdc) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_get_ring: tdc %d "
+ "ring $%p",
+ tdc, tx_rings->rings[index]));
+ return (p_tx_ring_t)(tx_rings->rings[index]);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_ring"));
+ return (NULL);
+}
+
+static p_tx_mbox_t
+nxge_txdma_get_mbox(p_nxge_t nxgep, uint16_t channel)
+{
+ int index, tdc, ndmas;
+ p_tx_rings_t tx_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+ p_tx_mbox_t *tx_mbox_p;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_mbox"));
+
+ tx_rings = nxgep->tx_rings;
+ if (tx_rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_txdma_get_mbox: NULL ring pointer"));
+ return (NULL);
+ }
+
+ tx_mbox_areas_p = nxgep->tx_mbox_areas_p;
+ if (tx_mbox_areas_p == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_txdma_get_mbox: NULL mbox pointer"));
+ return (NULL);
+ }
+
+ tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p;
+
+ ndmas = tx_rings->ndmas;
+ if (!ndmas) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_txdma_get_mbox: no channel allocated"));
+ return (NULL);
+ }
+
+ if (tx_rings->rings == NULL) {
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "<== nxge_txdma_get_mbox: NULL rings pointer"));
+ return (NULL);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_get_mbox: "
+ "tx_rings $%p tx_desc_rings $%p ndmas %d",
+ tx_rings, tx_rings, ndmas));
+
+ for (index = 0; index < ndmas; index++) {
+ tdc = tx_rings->rings[index]->tdc;
+ NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
+ "==> nxge_txdma_get_mbox: channel %d", tdc));
+ if (channel == tdc) {
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "<== nxge_txdma_get_mbox: tdc %d "
+ "ring $%p",
+ tdc, tx_rings->rings[index]));
+ return (p_tx_mbox_t)(tx_mbox_p[index]);
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_mbox"));
+ return (NULL);
+}
+
+/*ARGSUSED*/
+static nxge_status_t
+nxge_tx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp, tx_cs_t cs)
+{
+ npi_handle_t handle;
+ npi_status_t rs;
+ uint8_t channel;
+ p_tx_ring_t *tx_rings;
+ p_tx_ring_t tx_ring_p;
+ p_nxge_tx_ring_stats_t tdc_stats;
+ boolean_t txchan_fatal = B_FALSE;
+ nxge_status_t status = NXGE_OK;
+ tdmc_inj_par_err_t par_err;
+ uint32_t value;
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "==> nxge_tx_err_evnts"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ channel = ldvp->channel;
+
+ tx_rings = nxgep->tx_rings->rings;
+ tx_ring_p = tx_rings[index];
+ tdc_stats = tx_ring_p->tdc_stats;
+ if ((cs.bits.ldw.pkt_size_err) || (cs.bits.ldw.pref_buf_par_err) ||
+ (cs.bits.ldw.nack_pref) || (cs.bits.ldw.nack_pkt_rd) ||
+ (cs.bits.ldw.conf_part_err) || (cs.bits.ldw.pkt_prt_err)) {
+ if ((rs = npi_txdma_ring_error_get(handle, channel,
+ &tdc_stats->errlog)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+ }
+
+ if (cs.bits.ldw.mbox_err) {
+ tdc_stats->mbox_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_MBOX_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: mailbox", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.pkt_size_err) {
+ tdc_stats->pkt_size_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: pkt_size_err", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.tx_ring_oflow) {
+ tdc_stats->tx_ring_oflow++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: tx_ring_oflow", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.pref_buf_par_err) {
+ tdc_stats->pre_buf_par_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: pre_buf_par_err", channel));
+ /* Clear error injection source for parity error */
+ (void) npi_txdma_inj_par_error_get(handle, &value);
+ par_err.value = value;
+ par_err.bits.ldw.inject_parity_error &= ~(1 << channel);
+ (void) npi_txdma_inj_par_error_set(handle, par_err.value);
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.nack_pref) {
+ tdc_stats->nack_pref++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_NACK_PREF);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: nack_pref", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.nack_pkt_rd) {
+ tdc_stats->nack_pkt_rd++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_NACK_PKT_RD);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: nack_pkt_rd", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.conf_part_err) {
+ tdc_stats->conf_part_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_CONF_PART_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: config_partition_err", channel));
+ txchan_fatal = B_TRUE;
+ }
+ if (cs.bits.ldw.pkt_prt_err) {
+ tdc_stats->pkt_part_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel,
+ NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_tx_err_evnts(channel %d): "
+ "fatal error: pkt_prt_err", channel));
+ txchan_fatal = B_TRUE;
+ }
+
+ /* Clear error injection source in case this is an injected error */
+ TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, channel, 0);
+
+ if (txchan_fatal) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_tx_err_evnts: "
+ " fatal error on channel %d cs 0x%llx\n",
+ channel, cs.value));
+ status = nxge_txdma_fatal_err_recover(nxgep, channel,
+ tx_ring_p);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+
+ NXGE_DEBUG_MSG((nxgep, RX2_CTL, "<== nxge_tx_err_evnts"));
+
+ return (status);
+}
+
+static nxge_status_t
+nxge_txdma_fatal_err_recover(p_nxge_t nxgep, uint16_t channel,
+ p_tx_ring_t tx_ring_p)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_tx_mbox_t tx_mbox_p;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fatal_err_recover"));
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from TxDMAChannel#%d error...", channel));
+
+ /*
+ * Stop the dma channel waits for the stop done.
+ * If the stop done bit is not set, then create
+ * an error.
+ */
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel stop..."));
+ MUTEX_ENTER(&tx_ring_p->lock);
+ rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_fatal_err_recover (channel %d): "
+ "stop failed ", channel));
+ goto fail;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reclaim..."));
+ (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
+
+ /*
+ * Reset TXDMA channel
+ */
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reset..."));
+ if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, channel)) !=
+ NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_fatal_err_recover (channel %d)"
+ " reset channel failed 0x%x", channel, rs));
+ goto fail;
+ }
+
+ /*
+ * Reset the tail (kick) register to 0.
+ * (Hardware will not reset it. Tx overflow fatal
+ * error if tail is not set to 0 after reset!
+ */
+ TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0);
+
+ /* Restart TXDMA channel */
+
+ /*
+ * Initialize the TXDMA channel specific FZC control
+ * configurations. These FZC registers are pertaining
+ * to each TX channel (i.e. logical pages).
+ */
+ tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel);
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel restart..."));
+ status = nxge_init_fzc_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ if (status != NXGE_OK)
+ goto fail;
+
+ /*
+ * Initialize the event masks.
+ */
+ tx_ring_p->tx_evmask.value = 0;
+ status = nxge_init_txdma_channel_event_mask(nxgep, channel,
+ &tx_ring_p->tx_evmask);
+ if (status != NXGE_OK)
+ goto fail;
+
+ tx_ring_p->wr_index_wrap = B_FALSE;
+ tx_ring_p->wr_index = 0;
+ tx_ring_p->rd_index = 0;
+
+ /*
+ * Load TXDMA descriptors, buffers, mailbox,
+ * initialise the DMA channels and
+ * enable each DMA channel.
+ */
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel enable..."));
+ status = nxge_enable_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ MUTEX_EXIT(&tx_ring_p->lock);
+ if (status != NXGE_OK)
+ goto fail;
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Successful, TxDMAChannel#%d Restored",
+ channel));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fatal_err_recover"));
+
+ return (NXGE_OK);
+
+fail:
+ MUTEX_EXIT(&tx_ring_p->lock);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "nxge_txdma_fatal_err_recover (channel %d): "
+ "failed to recover this txdma channel", channel));
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_tx_port_fatal_err_recover(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ p_tx_ring_t *tx_desc_rings;
+ p_tx_rings_t tx_rings;
+ p_tx_ring_t tx_ring_p;
+ p_tx_mbox_t tx_mbox_p;
+ int i, ndmas;
+ uint16_t channel;
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_tx_port_fatal_err_recover"));
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from TxPort error..."));
+
+ /*
+ * Stop the dma channel waits for the stop done.
+ * If the stop done bit is not set, then create
+ * an error.
+ */
+
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort stop all DMA channels..."));
+
+ tx_rings = nxgep->tx_rings;
+ tx_desc_rings = tx_rings->rings;
+ ndmas = tx_rings->ndmas;
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ tx_ring_p = tx_rings->rings[i];
+ MUTEX_ENTER(&tx_ring_p->lock);
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ channel = tx_desc_rings[i]->tdc;
+ tx_ring_p = tx_rings->rings[i];
+ rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_fatal_err_recover (channel %d): "
+ "stop failed ", channel));
+ goto fail;
+ }
+ }
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort reclaim all DMA channels..."));
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ tx_ring_p = tx_rings->rings[i];
+ (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0);
+ }
+
+ /*
+ * Reset TXDMA channel
+ */
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort reset all DMA channels..."));
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ channel = tx_desc_rings[i]->tdc;
+ tx_ring_p = tx_rings->rings[i];
+ if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET,
+ channel)) != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_txdma_fatal_err_recover (channel %d)"
+ " reset channel failed 0x%x", channel, rs));
+ goto fail;
+ }
+
+ /*
+ * Reset the tail (kick) register to 0.
+ * (Hardware will not reset it. Tx overflow fatal
+ * error if tail is not set to 0 after reset!
+ */
+
+ TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0);
+
+ }
+
+ /*
+ * Initialize the TXDMA channel specific FZC control
+ * configurations. These FZC registers are pertaining
+ * to each TX channel (i.e. logical pages).
+ */
+
+ /* Restart TXDMA channels */
+
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort re-start all DMA channels..."));
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ channel = tx_desc_rings[i]->tdc;
+ tx_ring_p = tx_rings->rings[i];
+ tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel);
+ status = nxge_init_fzc_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ tx_ring_p->tx_evmask.value = 0;
+ /*
+ * Initialize the event masks.
+ */
+ status = nxge_init_txdma_channel_event_mask(nxgep, channel,
+ &tx_ring_p->tx_evmask);
+
+ tx_ring_p->wr_index_wrap = B_FALSE;
+ tx_ring_p->wr_index = 0;
+ tx_ring_p->rd_index = 0;
+
+ if (status != NXGE_OK)
+ goto fail;
+ if (status != NXGE_OK)
+ goto fail;
+ }
+
+ /*
+ * Load TXDMA descriptors, buffers, mailbox,
+ * initialise the DMA channels and
+ * enable each DMA channel.
+ */
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort re-enable all DMA channels..."));
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ channel = tx_desc_rings[i]->tdc;
+ tx_ring_p = tx_rings->rings[i];
+ tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel);
+ status = nxge_enable_txdma_channel(nxgep, channel,
+ tx_ring_p, tx_mbox_p);
+ if (status != NXGE_OK)
+ goto fail;
+ }
+
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ tx_ring_p = tx_rings->rings[i];
+ MUTEX_EXIT(&tx_ring_p->lock);
+ }
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Successful, TxPort Restored"));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover"));
+
+ return (NXGE_OK);
+
+fail:
+ for (i = 0; i < ndmas; i++) {
+ if (tx_desc_rings[i] == NULL) {
+ continue;
+ }
+ tx_ring_p = tx_rings->rings[i];
+ MUTEX_EXIT(&tx_ring_p->lock);
+ }
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+ NXGE_DEBUG_MSG((nxgep, TX_CTL,
+ "nxge_txdma_fatal_err_recover (channel %d): "
+ "failed to recover this txdma channel"));
+
+ return (status);
+}
+
+
+void
+nxge_txdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan)
+{
+ tdmc_intr_dbg_t tdi;
+ tdmc_inj_par_err_t par_err;
+ uint32_t value;
+ npi_handle_t handle;
+
+ switch (err_id) {
+
+ case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ /* Clear error injection source for parity error */
+ (void) npi_txdma_inj_par_error_get(handle, &value);
+ par_err.value = value;
+ par_err.bits.ldw.inject_parity_error &= ~(1 << chan);
+ (void) npi_txdma_inj_par_error_set(handle, par_err.value);
+
+ par_err.bits.ldw.inject_parity_error = (1 << chan);
+ (void) npi_txdma_inj_par_error_get(handle, &value);
+ par_err.value = value;
+ par_err.bits.ldw.inject_parity_error |= (1 << chan);
+ cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INJ_PAR_ERR_REG\n",
+ (unsigned long long)par_err.value);
+ (void) npi_txdma_inj_par_error_set(handle, par_err.value);
+ break;
+
+ case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
+ case NXGE_FM_EREPORT_TDMC_NACK_PREF:
+ case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
+ case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
+ case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
+ case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
+ case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
+ TXDMA_REG_READ64(nxgep->npi_handle, TDMC_INTR_DBG_REG,
+ chan, &tdi.value);
+ if (err_id == NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR)
+ tdi.bits.ldw.pref_buf_par_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_MBOX_ERR)
+ tdi.bits.ldw.mbox_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PREF)
+ tdi.bits.ldw.nack_pref = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PKT_RD)
+ tdi.bits.ldw.nack_pkt_rd = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR)
+ tdi.bits.ldw.pkt_size_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW)
+ tdi.bits.ldw.tx_ring_oflow = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_CONF_PART_ERR)
+ tdi.bits.ldw.conf_part_err = 1;
+ else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR)
+ tdi.bits.ldw.pkt_part_err = 1;
+ cmn_err(CE_NOTE, "!Write 0x%lx to TDMC_INTR_DBG_REG\n",
+ tdi.value);
+ TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG,
+ chan, tdi.value);
+
+ break;
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_virtual.c b/usr/src/uts/sun4v/io/nxge/nxge_virtual.c
new file mode 100644
index 0000000000..204331fbf0
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_virtual.c
@@ -0,0 +1,4135 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/nxge/nxge_impl.h>
+#include <sys/nxge/nxge_mac.h>
+
+static void nxge_get_niu_property(dev_info_t *, niu_type_t *);
+static void nxge_get_mac_addr_properties(p_nxge_t);
+static nxge_status_t nxge_use_cfg_n2niu_properties(p_nxge_t);
+static void nxge_use_cfg_neptune_properties(p_nxge_t);
+static void nxge_use_cfg_dma_config(p_nxge_t);
+static void nxge_use_cfg_vlan_class_config(p_nxge_t);
+static void nxge_use_cfg_mac_class_config(p_nxge_t);
+static void nxge_use_cfg_class_config(p_nxge_t);
+static void nxge_use_cfg_link_cfg(p_nxge_t);
+static void nxge_setup_hw_pciconfig(p_nxge_t);
+static void nxge_setup_hw_vpd_rom_mac(p_nxge_t);
+static void nxge_set_hw_dma_config(p_nxge_t);
+static void nxge_set_hw_vlan_class_config(p_nxge_t);
+static void nxge_set_hw_mac_class_config(p_nxge_t);
+static void nxge_set_hw_class_config(p_nxge_t);
+
+static nxge_status_t nxge_use_default_dma_config_n2(p_nxge_t);
+
+static void nxge_ldgv_setup(p_nxge_ldg_t *ldgp, p_nxge_ldv_t *, uint8_t,
+ uint8_t, int *);
+static void nxge_init_mmac(p_nxge_t);
+
+uint32_t nxge_use_hw_property = 1;
+uint32_t nxge_groups_per_port = 2;
+
+extern uint32_t nxge_use_partition;
+extern uint32_t nxge_dma_obp_props_only;
+
+extern uint16_t nxge_rcr_timeout;
+extern uint16_t nxge_rcr_threshold;
+
+extern uint_t nxge_rx_intr(void *, void *);
+extern uint_t nxge_tx_intr(void *, void *);
+extern uint_t nxge_mif_intr(void *, void *);
+extern uint_t nxge_mac_intr(void *, void *);
+extern uint_t nxge_syserr_intr(void *, void *);
+extern void *nxge_list;
+
+#define NXGE_SHARED_REG_SW_SIM
+
+#ifdef NXGE_SHARED_REG_SW_SIM
+uint64_t global_dev_ctrl = 0;
+#endif
+
+#define MAX_SIBLINGS NXGE_MAX_PORTS
+
+
+extern uint32_t nxge_rbr_size;
+extern uint32_t nxge_rcr_size;
+extern uint32_t nxge_tx_ring_size;
+extern uint32_t nxge_rbr_spare_size;
+
+extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
+
+static uint8_t p2_tx_fair[2] = {12, 12};
+static uint8_t p2_tx_equal[2] = {12, 12};
+static uint8_t p4_tx_fair[4] = {6, 6, 6, 6};
+static uint8_t p4_tx_equal[4] = {6, 6, 6, 6};
+static uint8_t p2_rx_fair[2] = {8, 8};
+static uint8_t p2_rx_equal[2] = {8, 8};
+
+static uint8_t p4_rx_fair[4] = {4, 4, 4, 4};
+static uint8_t p4_rx_equal[4] = {4, 4, 4, 4};
+
+static uint8_t p2_rdcgrp_fair[2] = {4, 4};
+static uint8_t p2_rdcgrp_equal[2] = {4, 4};
+static uint8_t p4_rdcgrp_fair[4] = {2, 2, 1, 1};
+static uint8_t p4_rdcgrp_equal[4] = {2, 2, 2, 2};
+static uint8_t p2_rdcgrp_cls[2] = {1, 1};
+static uint8_t p4_rdcgrp_cls[4] = {1, 1, 1, 1};
+
+typedef enum {
+ DEFAULT = 0,
+ EQUAL,
+ FAIR,
+ CUSTOM,
+ CLASSIFY,
+ L2_CLASSIFY,
+ L3_DISTRIBUTE,
+ L3_CLASSIFY,
+ L3_TCAM,
+ CONFIG_TOKEN_NONE
+} config_token_t;
+
+static char *token_names[] = {
+ "default",
+ "equal",
+ "fair",
+ "custom",
+ "classify",
+ "l2_classify",
+ "l3_distribute",
+ "l3_classify",
+ "l3_tcam",
+ "none",
+};
+
+void nxge_virint_regs_dump(p_nxge_t nxgep);
+
+void
+nxge_virint_regs_dump(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_virint_regs_dump"));
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ (void) npi_vir_dump_pio_fzc_regs_one(handle);
+ (void) npi_vir_dump_ldgnum(handle);
+ (void) npi_vir_dump_ldsv(handle);
+ (void) npi_vir_dump_imask0(handle);
+ (void) npi_vir_dump_sid(handle);
+ (void) npi_mac_dump_regs(handle, nxgep->function_num);
+ (void) npi_ipp_dump_regs(handle, nxgep->function_num);
+ (void) npi_fflp_dump_regs(handle);
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_virint_regs_dump"));
+}
+
+/*
+ * For now: we hard coded the DMA configurations.
+ * and assume for one partition only.
+ *
+ * OBP. Then OBP will pass this partition's
+ * Neptune configurations to fcode to create
+ * properties for them.
+ *
+ * Since Neptune(PCI-E) and NIU (Niagara-2) has
+ * different bus interfaces, the driver needs
+ * to know which bus it is connected to.
+ * Ravinder suggested: create a device property.
+ * In partitioning environment, we cannot
+ * use .conf file (need to check). If conf changes,
+ * need to reboot the system.
+ * The following function assumes that we will
+ * retrieve its properties from a virtualized nexus driver.
+ */
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_cntlops(dev_info_t *dip, nxge_ctl_enum_t ctlop, void *arg, void *result)
+{
+ nxge_status_t status = NXGE_OK;
+ int instance;
+ p_nxge_t nxgep;
+#ifndef NXGE_SHARED_REG_SW_SIM
+ npi_handle_t handle;
+ uint16_t sr16, cr16;
+#endif
+ instance = ddi_get_instance(dip);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "Instance %d ",
+ instance));
+ if (nxge_list == NULL) {
+ NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
+ "nxge_cntlops: nxge_list null"));
+ return (NXGE_ERROR);
+ }
+ nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
+ if (nxgep == NULL) {
+ NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
+ "nxge_cntlops: nxgep null"));
+ return (NXGE_ERROR);
+ }
+#ifndef NXGE_SHARED_REG_SW_SIM
+ handle = nxgep->npi_reg_handle;
+#endif
+ switch (ctlop) {
+ case NXGE_CTLOPS_NIUTYPE:
+ nxge_get_niu_property(dip, (niu_type_t *)result);
+ return (status);
+ case NXGE_CTLOPS_GET_SHARED_REG:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ *(uint64_t *)result = global_dev_ctrl;
+ return (0);
+#else
+ status = npi_dev_func_sr_sr_get(handle, &sr16);
+ *(uint16_t *)result = sr16;
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_GET_SHARED_REG"));
+ return (0);
+#endif
+
+ case NXGE_CTLOPS_SET_SHARED_REG_LOCK:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl = *(uint64_t *)arg;
+ return (0);
+#else
+ status = NPI_FAILURE;
+ while (status != NPI_SUCCESS)
+ status = npi_dev_func_sr_lock_enter(handle);
+
+ sr16 = *(uint16_t *)arg;
+ status = npi_dev_func_sr_sr_set_only(handle, &sr16);
+ status = npi_dev_func_sr_lock_free(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
+ return (0);
+#endif
+
+ case NXGE_CTLOPS_UPDATE_SHARED_REG:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = NPI_FAILURE;
+ while (status != NPI_SUCCESS)
+ status = npi_dev_func_sr_lock_enter(handle);
+ status = npi_dev_func_sr_sr_get(handle, &sr16);
+ sr16 |= *(uint16_t *)arg;
+ status = npi_dev_func_sr_sr_set_only(handle, &sr16);
+ status = npi_dev_func_sr_lock_free(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
+ return (0);
+
+#endif
+
+ case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG_UL:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = npi_dev_func_sr_sr_get(handle, &sr16);
+ cr16 = *(uint16_t *)arg;
+ sr16 &= ~cr16;
+ status = npi_dev_func_sr_sr_set_only(handle, &sr16);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
+ return (0);
+#endif
+
+ case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = NPI_FAILURE;
+ while (status != NPI_SUCCESS)
+ status = npi_dev_func_sr_lock_enter(handle);
+ status = npi_dev_func_sr_sr_get(handle, &sr16);
+ cr16 = *(uint16_t *)arg;
+ sr16 &= ~cr16;
+ status = npi_dev_func_sr_sr_set_only(handle, &sr16);
+ status = npi_dev_func_sr_lock_free(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
+ return (0);
+#endif
+
+ case NXGE_CTLOPS_GET_LOCK_BLOCK:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = NPI_FAILURE;
+ while (status != NPI_SUCCESS)
+ status = npi_dev_func_sr_lock_enter(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_BLOCK"));
+ return (0);
+#endif
+ case NXGE_CTLOPS_GET_LOCK_TRY:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = npi_dev_func_sr_lock_enter(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_TRY"));
+ if (status == NPI_SUCCESS)
+ return (NXGE_OK);
+ else
+ return (NXGE_ERROR);
+#endif
+ case NXGE_CTLOPS_FREE_LOCK:
+#ifdef NXGE_SHARED_REG_SW_SIM
+ global_dev_ctrl |= *(uint64_t *)arg;
+ return (0);
+#else
+ status = npi_dev_func_sr_lock_free(handle);
+ NXGE_DEBUG_MSG((NULL, VIR_CTL,
+ "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_FREE"));
+ if (status == NPI_SUCCESS)
+ return (NXGE_OK);
+ else
+ return (NXGE_ERROR);
+#endif
+
+ default:
+ status = NXGE_ERROR;
+ }
+
+ return (status);
+}
+
+void
+nxge_common_lock_get(p_nxge_t nxgep)
+{
+ uint32_t status = NPI_FAILURE;
+ npi_handle_t handle;
+
+#if defined(NXGE_SHARE_REG_SW_SIM)
+ return;
+#endif
+ handle = nxgep->npi_reg_handle;
+ while (status != NPI_SUCCESS)
+ status = npi_dev_func_sr_lock_enter(handle);
+
+}
+
+
+void
+nxge_common_lock_free(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+#if defined(NXGE_SHARE_REG_SW_SIM)
+ return;
+#endif
+ handle = nxgep->npi_reg_handle;
+ (void) npi_dev_func_sr_lock_free(handle);
+}
+
+static void
+nxge_get_niu_property(dev_info_t *dip, niu_type_t *niu_type)
+{
+ uchar_t *prop_val;
+ uint_t prop_len;
+
+ *niu_type = NEPTUNE;
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0,
+ "niu-type", (uchar_t **)&prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ if (strncmp("niu", (caddr_t)prop_val, (size_t)prop_len) == 0) {
+ *niu_type = N2_NIU;
+ }
+ ddi_prop_free(prop_val);
+ }
+}
+
+static config_token_t
+nxge_get_config_token(char *prop)
+{
+ config_token_t token = DEFAULT;
+ while (token < CONFIG_TOKEN_NONE) {
+ if (strncmp(prop, token_names[token], 4) == 0)
+ break;
+ token++;
+ }
+ return (token);
+}
+
+
+/* per port */
+
+static nxge_status_t
+nxge_update_rxdma_grp_properties(p_nxge_t nxgep, config_token_t token,
+ dev_info_t *s_dip[])
+{
+ nxge_status_t status = NXGE_OK;
+ int ddi_status;
+ int num_ports = nxgep->nports;
+ int port, bits, j;
+ uint8_t start_grp = 0, num_grps = 0;
+ p_nxge_param_t param_arr;
+ uint32_t grp_bitmap[MAX_SIBLINGS];
+ int custom_start_grp[MAX_SIBLINGS];
+ int custom_num_grp[MAX_SIBLINGS];
+ uint8_t bad_config = B_FALSE;
+
+ char *start_prop, *num_prop, *cfg_prop;
+
+ start_grp = 0;
+ param_arr = nxgep->param_arr;
+
+ start_prop = param_arr[param_rdc_grps_start].fcode_name;
+ num_prop = param_arr[param_rx_rdc_grps].fcode_name;
+
+ switch (token) {
+ case FAIR:
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_grp[port] =
+ (num_ports == 4) ?
+ p4_rdcgrp_fair[port] :
+ p2_rdcgrp_fair[port];
+ custom_start_grp[port] = start_grp;
+ start_grp += custom_num_grp[port];
+ }
+
+ break;
+
+ case EQUAL:
+ cfg_prop = "equal";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_grp[port] =
+ (num_ports == 4) ?
+ p4_rdcgrp_equal[port] :
+ p2_rdcgrp_equal[port];
+ custom_start_grp[port] = start_grp;
+ start_grp += custom_num_grp[port];
+ }
+
+ break;
+
+
+ case CLASSIFY:
+ cfg_prop = "classify";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_grp[port] = (num_ports == 4) ?
+ p4_rdcgrp_cls[port] : p2_rdcgrp_cls[port];
+ custom_start_grp[port] = start_grp;
+ start_grp += custom_num_grp[port];
+ }
+
+ break;
+
+ case CUSTOM:
+ cfg_prop = "custom";
+ /* See if it is good config */
+ num_grps = 0;
+ for (port = 0; port < num_ports; port++) {
+ custom_start_grp[port] =
+ ddi_prop_get_int(DDI_DEV_T_NONE, s_dip[port],
+ DDI_PROP_DONTPASS, start_prop, -1);
+ if ((custom_start_grp[port] == -1) ||
+ (custom_start_grp[port] >=
+ NXGE_MAX_RDC_GRPS)) {
+ bad_config = B_TRUE;
+ break;
+ }
+
+ custom_num_grp[port] = ddi_prop_get_int(
+ DDI_DEV_T_NONE,
+ s_dip[port],
+ DDI_PROP_DONTPASS,
+ num_prop, -1);
+
+ if ((custom_num_grp[port] == -1) ||
+ (custom_num_grp[port] >
+ NXGE_MAX_RDC_GRPS) ||
+ ((custom_num_grp[port] +
+ custom_start_grp[port]) >=
+ NXGE_MAX_RDC_GRPS)) {
+ bad_config = B_TRUE;
+ break;
+ }
+
+ num_grps += custom_num_grp[port];
+ if (num_grps > NXGE_MAX_RDC_GRPS) {
+ bad_config = B_TRUE;
+ break;
+ }
+
+ grp_bitmap[port] = 0;
+ for (bits = 0;
+ bits < custom_num_grp[port];
+ bits++) {
+ grp_bitmap[port] |=
+ (1 << (bits + custom_start_grp[port]));
+ }
+
+ }
+
+ if (bad_config == B_FALSE) {
+ /* check for overlap */
+ for (port = 0; port < num_ports - 1; port++) {
+ for (j = port + 1; j < num_ports; j++) {
+ if (grp_bitmap[port] &
+ grp_bitmap[j]) {
+ bad_config = B_TRUE;
+ break;
+ }
+ }
+ if (bad_config == B_TRUE)
+ break;
+ }
+ }
+
+ if (bad_config == B_TRUE) {
+ /* use default config */
+ for (port = 0; port < num_ports; port++) {
+ custom_num_grp[port] =
+ (num_ports == 4) ?
+ p4_rx_fair[port] : p2_rx_fair[port];
+ custom_start_grp[port] = start_grp;
+ start_grp += custom_num_grp[port];
+ }
+ }
+ break;
+
+ default:
+ /* use default config */
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_grp[port] = (num_ports == 4) ?
+ p4_rx_fair[port] : p2_rx_fair[port];
+ custom_start_grp[port] = start_grp;
+ start_grp += custom_num_grp[port];
+ }
+ break;
+ }
+
+ /* Now Update the rx properties */
+ for (port = 0; port < num_ports; port++) {
+ ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
+ "rxdma-grp-cfg", cfg_prop);
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating",
+ cfg_prop));
+ status |= NXGE_DDI_FAILED;
+ }
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ num_prop, custom_num_grp[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating",
+ num_prop));
+ status |= NXGE_DDI_FAILED;
+ }
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ start_prop, custom_start_grp[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating",
+ start_prop));
+ status |= NXGE_DDI_FAILED;
+ }
+ }
+ if (status & NXGE_DDI_FAILED)
+ status |= NXGE_ERROR;
+
+ return (status);
+
+}
+
+
+static nxge_status_t
+nxge_update_rxdma_properties(p_nxge_t nxgep, config_token_t token,
+ dev_info_t *s_dip[])
+{
+ nxge_status_t status = NXGE_OK;
+ int ddi_status;
+ int num_ports = nxgep->nports;
+ int port, bits, j;
+ uint8_t start_rdc = 0, num_rdc = 0;
+ p_nxge_param_t param_arr;
+ uint32_t rdc_bitmap[MAX_SIBLINGS];
+ int custom_start_rdc[MAX_SIBLINGS];
+ int custom_num_rdc[MAX_SIBLINGS];
+ uint8_t bad_config = B_FALSE;
+ int *prop_val;
+ uint_t prop_len;
+ char *start_rdc_prop, *num_rdc_prop, *cfg_prop;
+
+ start_rdc = 0;
+ param_arr = nxgep->param_arr;
+
+ start_rdc_prop = param_arr[param_rxdma_channels_begin].fcode_name;
+ num_rdc_prop = param_arr[param_rxdma_channels].fcode_name;
+
+ switch (token) {
+ case FAIR:
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_rdc[port] = (num_ports == 4) ?
+ p4_rx_fair[port] : p2_rx_fair[port];
+ custom_start_rdc[port] = start_rdc;
+ start_rdc += custom_num_rdc[port];
+ }
+
+ break;
+
+ case EQUAL:
+ cfg_prop = "equal";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_rdc[port] = (num_ports == 4) ?
+ p4_rx_equal[port] :
+ p2_rx_equal[port];
+ custom_start_rdc[port] = start_rdc;
+ start_rdc += custom_num_rdc[port];
+ }
+
+ break;
+
+ case CUSTOM:
+ cfg_prop = "custom";
+ /* See if it is good config */
+ num_rdc = 0;
+ for (port = 0; port < num_ports; port++) {
+ ddi_status = ddi_prop_lookup_int_array(
+ DDI_DEV_T_ANY,
+ s_dip[port], 0,
+ start_rdc_prop,
+ &prop_val,
+ &prop_len);
+ if (ddi_status == DDI_SUCCESS)
+ custom_start_rdc[port] = *prop_val;
+ else {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom start port %d"
+ " read failed ",
+ " rxdma-cfg", port));
+ bad_config = B_TRUE;
+ status |= NXGE_DDI_FAILED;
+ }
+ if ((custom_start_rdc[port] == -1) ||
+ (custom_start_rdc[port] >=
+ NXGE_MAX_RDCS)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom start %d"
+ " out of range %x ",
+ " rxdma-cfg",
+ port,
+ custom_start_rdc[port]));
+ bad_config = B_TRUE;
+ break;
+ }
+
+ ddi_status = ddi_prop_lookup_int_array(
+ DDI_DEV_T_ANY,
+ s_dip[port],
+ 0,
+ num_rdc_prop,
+ &prop_val,
+ &prop_len);
+
+ if (ddi_status == DDI_SUCCESS)
+ custom_num_rdc[port] = *prop_val;
+ else {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom num port %d"
+ " read failed ",
+ "rxdma-cfg", port));
+ bad_config = B_TRUE;
+ status |= NXGE_DDI_FAILED;
+ }
+
+ if ((custom_num_rdc[port] == -1) ||
+ (custom_num_rdc[port] >
+ NXGE_MAX_RDCS) ||
+ ((custom_num_rdc[port] +
+ custom_start_rdc[port]) >
+ NXGE_MAX_RDCS)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom num %d"
+ " out of range %x ",
+ " rxdma-cfg",
+ port,
+ custom_num_rdc[port]));
+ bad_config = B_TRUE;
+ break;
+ }
+
+ num_rdc += custom_num_rdc[port];
+ if (num_rdc > NXGE_MAX_RDCS) {
+ bad_config = B_TRUE;
+ break;
+ }
+
+ rdc_bitmap[port] = 0;
+ for (bits = 0;
+ bits < custom_num_rdc[port]; bits++) {
+ rdc_bitmap[port] |=
+ (1 <<
+ (bits + custom_start_rdc[port]));
+ }
+
+ }
+
+ if (bad_config == B_FALSE) {
+ /* check for overlap */
+ for (port = 0; port < num_ports - 1; port++) {
+ for (j = port + 1; j < num_ports; j++) {
+ if (rdc_bitmap[port] &
+ rdc_bitmap[j]) {
+ NXGE_DEBUG_MSG((nxgep,
+ CFG_CTL,
+ " rxdma-cfg"
+ " property custom"
+ " bit overlap"
+ " %d %d ",
+ port, j));
+ bad_config = B_TRUE;
+ break;
+ }
+ }
+ if (bad_config == B_TRUE)
+ break;
+ }
+ }
+
+ if (bad_config == B_TRUE) {
+ /* use default config */
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " rxdma-cfg property:"
+ " bad custom config:"
+ " use default"));
+
+ for (port = 0; port < num_ports; port++) {
+ custom_num_rdc[port] =
+ (num_ports == 4) ?
+ p4_rx_fair[port] :
+ p2_rx_fair[port];
+ custom_start_rdc[port] = start_rdc;
+ start_rdc += custom_num_rdc[port];
+ }
+ }
+ break;
+
+ default:
+ /* use default config */
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_rdc[port] = (num_ports == 4) ?
+ p4_rx_fair[port] : p2_rx_fair[port];
+ custom_start_rdc[port] = start_rdc;
+ start_rdc += custom_num_rdc[port];
+ }
+ break;
+ }
+
+ /* Now Update the rx properties */
+ for (port = 0; port < num_ports; port++) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " update property rxdma-cfg with %s ",
+ cfg_prop));
+ ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
+ "rxdma-cfg", cfg_prop);
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property rxdma-cfg"
+ " is not updating to %s",
+ cfg_prop));
+ status |= NXGE_DDI_FAILED;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
+ num_rdc_prop, custom_num_rdc[port]));
+
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ num_rdc_prop, custom_num_rdc[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating with %d",
+ num_rdc_prop,
+ custom_num_rdc[port]));
+ status |= NXGE_DDI_FAILED;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
+ start_rdc_prop, custom_start_rdc[port]));
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ start_rdc_prop,
+ custom_start_rdc[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s"
+ " not updating with %d ",
+ start_rdc_prop,
+ custom_start_rdc[port]));
+ status |= NXGE_DDI_FAILED;
+ }
+ }
+ if (status & NXGE_DDI_FAILED)
+ status |= NXGE_ERROR;
+ return (status);
+
+}
+
+static nxge_status_t
+nxge_update_txdma_properties(p_nxge_t nxgep, config_token_t token,
+ dev_info_t *s_dip[])
+{
+ nxge_status_t status = NXGE_OK;
+ int ddi_status = DDI_SUCCESS;
+ int num_ports = nxgep->nports;
+ int port, bits, j;
+ uint8_t start_tdc = 0, num_tdc = 0;
+ p_nxge_param_t param_arr;
+ uint32_t tdc_bitmap[MAX_SIBLINGS];
+ int custom_start_tdc[MAX_SIBLINGS];
+ int custom_num_tdc[MAX_SIBLINGS];
+ uint8_t bad_config = B_FALSE;
+ int *prop_val;
+ uint_t prop_len;
+ char *start_tdc_prop, *num_tdc_prop, *cfg_prop;
+
+ start_tdc = 0;
+ param_arr = nxgep->param_arr;
+
+ start_tdc_prop = param_arr[param_txdma_channels_begin].fcode_name;
+ num_tdc_prop = param_arr[param_txdma_channels].fcode_name;
+
+ switch (token) {
+ case FAIR:
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_tdc[port] = (num_ports == 4) ?
+ p4_tx_fair[port] : p2_tx_fair[port];
+ custom_start_tdc[port] = start_tdc;
+ start_tdc += custom_num_tdc[port];
+ }
+
+ break;
+
+ case EQUAL:
+ cfg_prop = "equal";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_tdc[port] = (num_ports == 4) ?
+ p4_tx_equal[port] :
+ p2_tx_equal[port];
+ custom_start_tdc[port] = start_tdc;
+ start_tdc += custom_num_tdc[port];
+ }
+
+ break;
+
+ case CUSTOM:
+ cfg_prop = "custom";
+ /* See if it is good config */
+ num_tdc = 0;
+ for (port = 0; port < num_ports; port++) {
+ ddi_status = ddi_prop_lookup_int_array(
+ DDI_DEV_T_ANY,
+ s_dip[port], 0,
+ start_tdc_prop,
+ &prop_val,
+ &prop_len);
+ if (ddi_status == DDI_SUCCESS)
+ custom_start_tdc[port] = *prop_val;
+ else {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom start port %d"
+ " read failed ",
+ " txdma-cfg", port));
+ bad_config = B_TRUE;
+ status |= NXGE_DDI_FAILED;
+ }
+ if ((custom_start_tdc[port] == -1) ||
+ (custom_start_tdc[port] >=
+ NXGE_MAX_RDCS)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom start %d"
+ " out of range %x ",
+ " txdma-cfg",
+ port,
+ custom_start_tdc[port]));
+ bad_config = B_TRUE;
+ break;
+ }
+
+ ddi_status = ddi_prop_lookup_int_array(
+ DDI_DEV_T_ANY,
+ s_dip[port],
+ 0,
+ num_tdc_prop,
+ &prop_val,
+ &prop_len);
+
+ if (ddi_status == DDI_SUCCESS)
+ custom_num_tdc[port] = *prop_val;
+ else {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom num port %d"
+ " read failed ",
+ " txdma-cfg", port));
+ bad_config = B_TRUE;
+ status |= NXGE_DDI_FAILED;
+ }
+
+ if ((custom_num_tdc[port] == -1) ||
+ (custom_num_tdc[port] >
+ NXGE_MAX_TDCS) ||
+ ((custom_num_tdc[port] +
+ custom_start_tdc[port]) >
+ NXGE_MAX_TDCS)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s custom num %d"
+ " out of range %x ",
+ " rxdma-cfg",
+ port,
+ custom_num_tdc[port]));
+ bad_config = B_TRUE;
+ break;
+ }
+
+ num_tdc += custom_num_tdc[port];
+ if (num_tdc > NXGE_MAX_TDCS) {
+ bad_config = B_TRUE;
+ break;
+ }
+
+ tdc_bitmap[port] = 0;
+ for (bits = 0;
+ bits < custom_num_tdc[port]; bits++) {
+ tdc_bitmap[port] |=
+ (1 <<
+ (bits + custom_start_tdc[port]));
+ }
+
+ }
+
+ if (bad_config == B_FALSE) {
+ /* check for overlap */
+ for (port = 0; port < num_ports - 1; port++) {
+ for (j = port + 1; j < num_ports; j++) {
+ if (tdc_bitmap[port] &
+ tdc_bitmap[j]) {
+ NXGE_DEBUG_MSG((nxgep,
+ CFG_CTL,
+ " rxdma-cfg"
+ " property custom"
+ " bit overlap"
+ " %d %d ",
+ port, j));
+ bad_config = B_TRUE;
+ break;
+ }
+ }
+ if (bad_config == B_TRUE)
+ break;
+ }
+ }
+
+ if (bad_config == B_TRUE) {
+ /* use default config */
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " txdma-cfg property:"
+ " bad custom config:"
+ " use default"));
+
+ for (port = 0; port < num_ports; port++) {
+ custom_num_tdc[port] =
+ (num_ports == 4) ?
+ p4_tx_fair[port] :
+ p2_tx_fair[port];
+ custom_start_tdc[port] = start_tdc;
+ start_tdc += custom_num_tdc[port];
+ }
+ }
+ break;
+
+ default:
+ /* use default config */
+ cfg_prop = "fair";
+ for (port = 0; port < num_ports; port++) {
+ custom_num_tdc[port] = (num_ports == 4) ?
+ p4_tx_fair[port] : p2_tx_fair[port];
+ custom_start_tdc[port] = start_tdc;
+ start_tdc += custom_num_tdc[port];
+ }
+ break;
+ }
+
+ /* Now Update the tx properties */
+ for (port = 0; port < num_ports; port++) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " update property txdma-cfg with %s ",
+ cfg_prop));
+ ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port],
+ "txdma-cfg", cfg_prop);
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property txdma-cfg"
+ " is not updating to %s",
+ cfg_prop));
+ status |= NXGE_DDI_FAILED;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
+ num_tdc_prop, custom_num_tdc[port]));
+
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ num_tdc_prop, custom_num_tdc[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating with %d",
+ num_tdc_prop,
+ custom_num_tdc[port]));
+ status |= NXGE_DDI_FAILED;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ",
+ start_tdc_prop, custom_start_tdc[port]));
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port],
+ start_tdc_prop,
+ custom_start_tdc[port]);
+
+ if (ddi_status != DDI_PROP_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s"
+ " not updating with %d ",
+ start_tdc_prop,
+ custom_start_tdc[port]));
+ status |= NXGE_DDI_FAILED;
+ }
+ }
+ if (status & NXGE_DDI_FAILED)
+ status |= NXGE_ERROR;
+ return (status);
+
+}
+
+
+
+static nxge_status_t
+nxge_update_cfg_properties(p_nxge_t nxgep, uint32_t flags,
+ config_token_t token,
+ dev_info_t *s_dip[])
+{
+
+ nxge_status_t status = NXGE_OK;
+
+ switch (flags) {
+ case COMMON_TXDMA_CFG:
+ if (nxge_dma_obp_props_only == 0)
+ status = nxge_update_txdma_properties(nxgep,
+ token, s_dip);
+ break;
+ case COMMON_RXDMA_CFG:
+ if (nxge_dma_obp_props_only == 0)
+ status = nxge_update_rxdma_properties(nxgep,
+ token, s_dip);
+
+ break;
+ case COMMON_RXDMA_GRP_CFG:
+ status = nxge_update_rxdma_grp_properties(nxgep,
+ token, s_dip);
+ break;
+ default:
+ return (NXGE_ERROR);
+ }
+ return (status);
+}
+
+
+
+/*
+ * verify consistence.
+ * (May require publishing the properties on all the ports.
+ *
+ * What if properties are published on function 0 device only?
+ *
+ *
+ * rxdma-cfg, txdma-cfg, rxdma-grp-cfg (required )
+ * What about class configs?
+ *
+ * If consistent, update the property on all the siblings.
+ * set a flag on hardware shared register
+ * The rest of the siblings will check the flag
+ * if the flag is set, they will use the updated property
+ * without doing any validation.
+ */
+
+
+nxge_status_t
+nxge_cfg_verify_set_classify_prop(p_nxge_t nxgep, char *prop,
+ uint64_t known_cfg,
+ uint32_t override,
+ dev_info_t *c_dip[])
+{
+ nxge_status_t status = NXGE_OK;
+ int ddi_status = DDI_SUCCESS;
+ int i = 0, found = 0, update_prop = B_TRUE;
+ int *cfg_val;
+ uint_t new_value, cfg_value[MAX_SIBLINGS];
+ uint_t prop_len;
+ uint_t known_cfg_value;
+
+ known_cfg_value = (uint_t)known_cfg;
+
+ if (override == B_TRUE) {
+ new_value = known_cfg_value;
+ for (i = 0; i < nxgep->nports; i++) {
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE,
+ c_dip[i], prop, new_value);
+#ifdef NXGE_DEBUG_ERROR
+ if (ddi_status != DDI_PROP_SUCCESS)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s failed update ", prop));
+#endif
+ }
+ if (ddi_status != DDI_PROP_SUCCESS)
+ return (NXGE_ERROR | NXGE_DDI_FAILED);
+ }
+
+ for (i = 0; i < nxgep->nports; i++) {
+ cfg_value[i] = known_cfg_value;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, c_dip[i], 0,
+ prop, &cfg_val,
+ &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ cfg_value[i] = *cfg_val;
+ ddi_prop_free(cfg_val);
+ found++;
+ }
+ }
+
+ if (found != i) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not specified on all ports",
+ prop));
+ if (found == 0) {
+ /* not specified: Use default */
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not specified"
+ " on any port:"
+ " Using default", prop));
+
+ new_value = known_cfg_value;
+ } else {
+ /* specified on some */
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not specified"
+ " on some ports:"
+ " Using default", prop));
+ /* ? use p0 value instead ? */
+ new_value = known_cfg_value;
+ }
+ } else {
+ /* check type and consistence */
+ /* found on all devices */
+ for (i = 1; i < found; i++) {
+ if (cfg_value[i] != cfg_value[i-1]) {
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s inconsistent:"
+ " Using default", prop));
+ new_value = known_cfg_value;
+ break;
+ }
+
+ /*
+ * Found on all the ports and consistent. Nothing to do.
+ */
+ update_prop = B_FALSE;
+ }
+
+ }
+
+ if (update_prop == B_TRUE) {
+ for (i = 0; i < nxgep->nports; i++) {
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE,
+ c_dip[i],
+ prop, new_value);
+#ifdef NXGE_DEBUG_ERROR
+ if (ddi_status != DDI_SUCCESS)
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " property %s not updating with %d"
+ " Using default",
+ prop, new_value));
+#endif
+ if (ddi_status != DDI_PROP_SUCCESS)
+ status |= NXGE_DDI_FAILED;
+ }
+ }
+ if (status & NXGE_DDI_FAILED)
+ status |= NXGE_ERROR;
+
+ return (status);
+}
+
+static uint64_t
+nxge_class_get_known_cfg(p_nxge_t nxgep,
+ int class_prop, int rx_quick_cfg)
+{
+
+ int start_prop;
+ uint64_t cfg_value;
+
+ p_nxge_param_t param_arr;
+ param_arr = nxgep->param_arr;
+
+ cfg_value = param_arr[class_prop].value;
+ start_prop = param_h1_init_value;
+
+ /* update the properties per quick config */
+
+ switch (rx_quick_cfg) {
+ case CFG_L3_WEB:
+ case CFG_L3_DISTRIBUTE:
+ cfg_value = nxge_classify_get_cfg_value(nxgep,
+ rx_quick_cfg,
+ class_prop - start_prop);
+ break;
+ default:
+ cfg_value = param_arr[class_prop].value;
+ break;
+ }
+
+ return (cfg_value);
+
+}
+
+
+static nxge_status_t
+nxge_cfg_verify_set_classify(p_nxge_t nxgep, dev_info_t *c_dip[])
+{
+
+ nxge_status_t status = NXGE_OK;
+ int rx_quick_cfg, class_prop, start_prop, end_prop;
+ char *prop_name;
+ int override = B_TRUE;
+ uint64_t cfg_value;
+ p_nxge_param_t param_arr;
+ param_arr = nxgep->param_arr;
+ rx_quick_cfg = param_arr[param_rx_quick_cfg].value;
+ start_prop = param_h1_init_value;
+ end_prop = param_class_opt_ipv6_sctp;
+ /* update the properties per quick config */
+
+
+ if (rx_quick_cfg == CFG_NOT_SPECIFIED)
+ override = B_FALSE;
+/*
+ * these parameter affect the classification outcome.
+ * these parameters are used to configure the Flow key and
+ * the TCAM key for each of the IP classes.
+ * Includee here are also the H1 and H2 initial values
+ * which affect the distribution as well as final hash value
+ * (hence the offset into RDC table and FCRAM bucket location)
+ *
+ */
+ for (class_prop = start_prop;
+ class_prop <= end_prop; class_prop++) {
+ prop_name = param_arr[class_prop].fcode_name;
+ cfg_value = nxge_class_get_known_cfg(nxgep,
+ class_prop,
+ rx_quick_cfg);
+ status = nxge_cfg_verify_set_classify_prop(nxgep,
+ prop_name, cfg_value,
+ override, c_dip);
+ }
+
+
+/*
+ * these properties do not affect the actual classification outcome.
+ * used to enable/disable or tune the fflp hardware
+ *
+ * fcram_access_ratio, tcam_access_ratio, tcam_enable, llc_snap_enable
+ *
+ */
+ override = B_FALSE;
+ for (class_prop = param_fcram_access_ratio;
+ class_prop <= param_llc_snap_enable;
+ class_prop++) {
+ prop_name = param_arr[class_prop].fcode_name;
+ cfg_value = param_arr[class_prop].value;
+ status = nxge_cfg_verify_set_classify_prop(nxgep, prop_name,
+ cfg_value, override, c_dip);
+ }
+ return (status);
+
+}
+
+
+
+nxge_status_t
+nxge_cfg_verify_set(p_nxge_t nxgep, uint32_t flag)
+{
+
+ nxge_status_t status = NXGE_OK;
+ int i = 0, found = 0;
+ int num_siblings;
+ dev_info_t *c_dip[MAX_SIBLINGS + 1];
+ char *prop_val[MAX_SIBLINGS];
+ config_token_t c_token[MAX_SIBLINGS];
+ char *prop;
+
+ if (nxge_dma_obp_props_only) {
+ return (NXGE_OK);
+ }
+
+ num_siblings = 0;
+ c_dip[num_siblings] = ddi_get_child(nxgep->p_dip);
+ while (c_dip[num_siblings]) {
+ c_dip[num_siblings + 1] =
+ ddi_get_next_sibling(c_dip[num_siblings]);
+ num_siblings++;
+ }
+
+
+ switch (flag) {
+ case COMMON_TXDMA_CFG:
+ prop = "txdma-cfg";
+ break;
+ case COMMON_RXDMA_CFG:
+ prop = "rxdma-cfg";
+ break;
+ case COMMON_RXDMA_GRP_CFG:
+ prop = "rxdma-grp-cfg";
+ break;
+ case COMMON_CLASS_CFG:
+ status = nxge_cfg_verify_set_classify(nxgep, c_dip);
+ return (status);
+ default:
+ return (NXGE_ERROR);
+ }
+
+
+ i = 0;
+ while (i < num_siblings) {
+ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, c_dip[i], 0,
+ prop, (char **)&prop_val[i]) ==
+ DDI_PROP_SUCCESS) {
+ c_token[i] = nxge_get_config_token(prop_val[i]);
+ ddi_prop_free(prop_val[i]);
+ found++;
+ } else
+ c_token[i] = CONFIG_TOKEN_NONE;
+ i++;
+ }
+
+
+ if (found != i) {
+ if (found == 0) {
+ /* not specified: Use default */
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not specified"
+ " on any port:"
+ " Using default",
+ prop));
+
+ status = nxge_update_cfg_properties(nxgep,
+ flag, FAIR, c_dip);
+ return (status);
+ } else {
+ /*
+ * if the convention is to use function 0 device
+ * then populate the other devices with this
+ * configuration.
+ *
+ * The other alternative is to use the default config.
+ */
+ /* not specified: Use default */
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not specified"
+ " on some ports:"
+ " Using default",
+ prop));
+ status = nxge_update_cfg_properties(nxgep,
+ flag, FAIR, c_dip);
+ return (status);
+ }
+ }
+ /* check type and consistence */
+ /* found on all devices */
+ for (i = 1; i < found; i++) {
+ if (c_token[i] != c_token[i-1]) {
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s inconsistent:"
+ " Using default", prop));
+
+ status = nxge_update_cfg_properties(nxgep,
+ flag, FAIR, c_dip);
+ return (status);
+ }
+ }
+ /*
+ * Found on all the ports
+ * check if it is custom configuration.
+ * if custom, then verify consistence
+ *
+ * finally create soft properties
+ */
+ status = nxge_update_cfg_properties(nxgep, flag, c_token[0], c_dip);
+
+ return (status);
+}
+
+
+
+nxge_status_t
+nxge_cfg_verify_set_quick_config(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ int ddi_status = DDI_SUCCESS;
+ char *prop_val;
+ char *rx_prop;
+ char *prop;
+ uint32_t cfg_value = CFG_NOT_SPECIFIED;
+ p_nxge_param_t param_arr;
+ param_arr = nxgep->param_arr;
+
+ rx_prop = param_arr[param_rx_quick_cfg].fcode_name;
+
+ prop = "rx-quick-cfg";
+ /*
+ * good value are
+ *
+ * "web-server"
+ * "generic-server"
+ * "l3-classify"
+ * "flow-classify"
+ */
+
+ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
+ prop, (char **)&prop_val) !=
+ DDI_PROP_SUCCESS) {
+
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL,
+ " property %s not specified:"
+ " using default ", prop));
+ cfg_value = CFG_NOT_SPECIFIED;
+ } else {
+ cfg_value = CFG_L3_DISTRIBUTE;
+ if (strncmp("web-server", (caddr_t)prop_val, 8) == 0) {
+ cfg_value = CFG_L3_WEB;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s: web server ", prop));
+ }
+ if (strncmp("generic-server", (caddr_t)prop_val, 8) == 0) {
+ cfg_value = CFG_L3_DISTRIBUTE;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " %s: distribute ", prop));
+ }
+ /* more */
+
+ ddi_prop_free(prop_val);
+ }
+
+ ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ rx_prop, cfg_value);
+ if (ddi_status != DDI_PROP_SUCCESS)
+ status |= NXGE_DDI_FAILED;
+#ifdef lint
+ status = status;
+#endif
+ /* now handle specified cases: */
+
+ if (status & NXGE_DDI_FAILED)
+ status |= NXGE_ERROR;
+
+ return (status);
+}
+
+
+
+static void
+nxge_use_cfg_link_cfg(p_nxge_t nxgep)
+{
+ int *prop_val;
+ uint_t prop_len;
+ dev_info_t *dip;
+ int speed;
+ int duplex;
+ int adv_autoneg_cap;
+ int adv_10gfdx_cap;
+ int adv_10ghdx_cap;
+ int adv_1000fdx_cap;
+ int adv_1000hdx_cap;
+ int adv_100fdx_cap;
+ int adv_100hdx_cap;
+ int adv_10fdx_cap;
+ int adv_10hdx_cap;
+ int status = DDI_SUCCESS;
+
+ dip = nxgep->dip;
+ /*
+ * first find out the card type and the supported
+ * link speeds and features
+ */
+ /* add code for card type */
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-autoneg-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10gfdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000hdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000fdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100fdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100hdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10fdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10hdx-cap",
+ &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ ddi_prop_free(prop_val);
+ goto nxge_map_myargs_to_gmii_exit;
+ }
+
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "speed",
+ (uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ if (strncmp("10000", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ speed = 10000;
+ } else if (strncmp("1000", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ speed = 1000;
+ } else if (strncmp("100", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ speed = 100;
+ } else if (strncmp("10", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ speed = 10;
+ } else if (strncmp("auto", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ speed = 0;
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_NOTE,
+ "speed property is invalid"
+ " reverting to auto"));
+ speed = 0;
+ }
+ ddi_prop_free(prop_val);
+ } else
+ speed = 0;
+
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "duplex",
+ (uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ if (strncmp("full", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ duplex = 2;
+ } else if (strncmp("half", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ duplex = 1;
+ } else if (strncmp("auto", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ duplex = 0;
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_NOTE,
+ "duplex property is invalid"
+ " reverting to auto"));
+ duplex = 0;
+ }
+ ddi_prop_free(prop_val);
+ } else
+ duplex = 0;
+
+ adv_autoneg_cap = (speed == 0) || (duplex == 0);
+ if (adv_autoneg_cap == 0) {
+ adv_10gfdx_cap = ((speed == 10000) && (duplex == 2));
+ adv_10ghdx_cap = adv_10gfdx_cap;
+ adv_10ghdx_cap |= ((speed == 10000) && (duplex == 1));
+ adv_1000fdx_cap = adv_10ghdx_cap;
+ adv_1000fdx_cap |= ((speed == 1000) && (duplex == 2));
+ adv_1000hdx_cap = adv_1000fdx_cap;
+ adv_1000hdx_cap |= ((speed == 1000) && (duplex == 1));
+ adv_100fdx_cap = adv_1000hdx_cap;
+ adv_100fdx_cap |= ((speed == 100) && (duplex == 2));
+ adv_100hdx_cap = adv_100fdx_cap;
+ adv_100hdx_cap |= ((speed == 100) && (duplex == 1));
+ adv_10fdx_cap = adv_100hdx_cap;
+ adv_10fdx_cap |= ((speed == 10) && (duplex == 2));
+ adv_10hdx_cap = adv_10fdx_cap;
+ adv_10hdx_cap |= ((speed == 10) && (duplex == 1));
+ } else if (speed == 0) {
+ adv_10gfdx_cap = (duplex == 2);
+ adv_10ghdx_cap = (duplex == 1);
+ adv_1000fdx_cap = (duplex == 2);
+ adv_1000hdx_cap = (duplex == 1);
+ adv_100fdx_cap = (duplex == 2);
+ adv_100hdx_cap = (duplex == 1);
+ adv_10fdx_cap = (duplex == 2);
+ adv_10hdx_cap = (duplex == 1);
+ }
+ if (duplex == 0) {
+ adv_10gfdx_cap = (speed == 0);
+ adv_10gfdx_cap |= (speed == 10000);
+ adv_10ghdx_cap = adv_10gfdx_cap;
+ adv_10ghdx_cap |= (speed == 10000);
+ adv_1000fdx_cap = adv_10ghdx_cap;
+ adv_1000fdx_cap |= (speed == 1000);
+ adv_1000hdx_cap = adv_1000fdx_cap;
+ adv_1000hdx_cap |= (speed == 1000);
+ adv_100fdx_cap = adv_1000hdx_cap;
+ adv_100fdx_cap |= (speed == 100);
+ adv_100hdx_cap = adv_100fdx_cap;
+ adv_100hdx_cap |= (speed == 100);
+ adv_10fdx_cap = adv_100hdx_cap;
+ adv_10fdx_cap |= (speed == 10);
+ adv_10hdx_cap = adv_10fdx_cap;
+ adv_10hdx_cap |= (speed == 10);
+ }
+
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-autoneg-cap", &adv_autoneg_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_exit;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-10gfdx-cap", &adv_10gfdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail1;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-10ghdx-cap", &adv_10ghdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail2;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-1000fdx-cap", &adv_1000fdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail3;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-1000hdx-cap", &adv_1000hdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail4;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-100fdx-cap", &adv_100fdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail5;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-100hdx-cap", &adv_100hdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail6;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-10fdx-cap", &adv_10fdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail7;
+
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
+ "adv-10hdx-cap", &adv_10hdx_cap, 1);
+ if (status)
+ goto nxge_map_myargs_to_gmii_fail8;
+
+ goto nxge_map_myargs_to_gmii_exit;
+
+nxge_map_myargs_to_gmii_fail9:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10hdx-cap");
+
+nxge_map_myargs_to_gmii_fail8:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10fdx-cap");
+
+nxge_map_myargs_to_gmii_fail7:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100hdx-cap");
+
+nxge_map_myargs_to_gmii_fail6:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100fdx-cap");
+
+nxge_map_myargs_to_gmii_fail5:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000hdx-cap");
+
+nxge_map_myargs_to_gmii_fail4:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000fdx-cap");
+
+nxge_map_myargs_to_gmii_fail3:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10ghdx-cap");
+
+nxge_map_myargs_to_gmii_fail2:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10gfdx-cap");
+
+nxge_map_myargs_to_gmii_fail1:
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-autoneg-cap");
+
+nxge_map_myargs_to_gmii_exit:
+ return;
+
+}
+
+
+nxge_status_t
+nxge_get_config_properties(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+ p_nxge_hw_list_t hw_p;
+ uint_t prop_len;
+ uchar_t *prop_val8;
+
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL, " ==> nxge_get_config_properties"));
+
+ if ((hw_p = nxgep->nxge_hw_p) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_get_config_properties:"
+ " common hardware not set",
+ nxgep->niu_type));
+ return (NXGE_ERROR);
+ }
+
+ /*
+ * Get info on how many ports Neptune card has.
+ */
+ switch (nxgep->niu_type) {
+ case N2_NIU:
+ nxgep->nports = 2;
+ nxgep->classifier.tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
+ if (nxgep->function_num > 1) {
+ return (NXGE_ERROR);
+ }
+ break;
+ case NEPTUNE_2:
+ if (nxgep->function_num > 1) {
+ return (NXGE_ERROR);
+ }
+ /* Set Board Version Number */
+ nxgep->board_ver = 0;
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
+ nxgep->dip,
+ 0, "board-model", &prop_val8,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ if (prop_len > 9) {
+ if ((prop_val8[9] == '0') &&
+ (prop_val8[10] == '4'))
+ nxgep->board_ver = 4;
+ }
+ ddi_prop_free(prop_val8);
+ }
+ status = nxge_espc_num_ports_get(nxgep);
+ if (status != NXGE_OK) {
+ return (NXGE_ERROR);
+ }
+ nxgep->classifier.tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
+ break;
+
+ case NEPTUNE:
+ default:
+ status = nxge_espc_num_ports_get(nxgep);
+ if (status != NXGE_OK) {
+ return (NXGE_ERROR);
+ }
+ nxgep->classifier.tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
+
+ break;
+ }
+
+ nxge_get_mac_addr_properties(nxgep);
+ /*
+ * read the configuration type.
+ * If none is specified, used default.
+ * Config types:
+ * equal: (default)
+ * DMA channels, RDC groups, TCAM, FCRAM are shared equally
+ * across all the ports.
+ *
+ * Fair:
+ * DMA channels, RDC groups, TCAM, FCRAM are shared
+ * proprtional
+ * to te port speed.
+ *
+ *
+ * custom:
+ * DMA channels, RDC groups, TCAM, FCRAM partition is
+ * specified in nxge.conf. Need to read each parameter
+ * and set up the parameters in nxge structures.
+ *
+ */
+ switch (nxgep->niu_type) {
+ case N2_NIU:
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL,
+ " ==> nxge_get_config_properties: N2"));
+ MUTEX_ENTER(&hw_p->nxge_cfg_lock);
+ if ((hw_p->flags & COMMON_CFG_VALID) !=
+ COMMON_CFG_VALID) {
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_RXDMA_GRP_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_CLASS_CFG);
+ hw_p->flags |= COMMON_CFG_VALID;
+ }
+ MUTEX_EXIT(&hw_p->nxge_cfg_lock);
+
+ status = nxge_use_cfg_n2niu_properties(nxgep);
+ break;
+
+ case NEPTUNE:
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL,
+ " ==> nxge_get_config_properties: Neptune"));
+ status = nxge_cfg_verify_set_quick_config(nxgep);
+ MUTEX_ENTER(&hw_p->nxge_cfg_lock);
+ if ((hw_p->flags & COMMON_CFG_VALID) !=
+ COMMON_CFG_VALID) {
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_TXDMA_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_RXDMA_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_RXDMA_GRP_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_CLASS_CFG);
+ hw_p->flags |= COMMON_CFG_VALID;
+ }
+
+ MUTEX_EXIT(&hw_p->nxge_cfg_lock);
+
+ nxge_use_cfg_neptune_properties(nxgep);
+
+ status = NXGE_OK;
+ break;
+
+ case NEPTUNE_2:
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL,
+ " ==> nxge_get_config_properties: Neptune-2"));
+ if (nxgep->function_num > 1)
+ return (NXGE_ERROR);
+ status = nxge_cfg_verify_set_quick_config(nxgep);
+ MUTEX_ENTER(&hw_p->nxge_cfg_lock);
+
+ if ((hw_p->flags & COMMON_CFG_VALID) !=
+ COMMON_CFG_VALID) {
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_TXDMA_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_RXDMA_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_RXDMA_GRP_CFG);
+ status = nxge_cfg_verify_set(nxgep,
+ COMMON_CLASS_CFG);
+ hw_p->flags |= COMMON_CFG_VALID;
+ }
+
+ MUTEX_EXIT(&hw_p->nxge_cfg_lock);
+
+ nxge_use_cfg_neptune_properties(nxgep);
+
+ status = NXGE_OK;
+ break;
+
+ default:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " nxge_get_config_properties:"
+ " unknown NIU type %x",
+ nxgep->niu_type));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, VPD_CTL, " <== nxge_get_config_properties"));
+ return (status);
+}
+
+
+static nxge_status_t
+nxge_use_cfg_n2niu_properties(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_n2niu_properties"));
+
+ status = nxge_use_default_dma_config_n2(nxgep);
+ if (status != NXGE_OK) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ " ==> nxge_use_cfg_n2niu_properties (err 0x%x)",
+ status));
+ return (status | NXGE_ERROR);
+ }
+
+ (void) nxge_use_cfg_vlan_class_config(nxgep);
+ (void) nxge_use_cfg_mac_class_config(nxgep);
+ (void) nxge_use_cfg_class_config(nxgep);
+
+ (void) nxge_use_cfg_link_cfg(nxgep);
+
+ /* Setup the VPD, expansion ROM, or MAC addresses configuration */
+ nxge_setup_hw_vpd_rom_mac(nxgep);
+
+ /*
+ * Read in the hardware (fcode) properties. Use the ndd array
+ * to read each property.
+ */
+ (void) nxge_get_param_soft_properties(nxgep);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_n2niu_properties"));
+
+ return (status);
+}
+
+
+static void
+nxge_use_cfg_neptune_properties(p_nxge_t nxgep)
+{
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " ==> nxge_use_cfg_neptune_properties"));
+
+ (void) nxge_use_cfg_dma_config(nxgep);
+ (void) nxge_use_cfg_vlan_class_config(nxgep);
+ (void) nxge_use_cfg_mac_class_config(nxgep);
+ (void) nxge_use_cfg_class_config(nxgep);
+
+ (void) nxge_use_cfg_link_cfg(nxgep);
+
+ /* Setup the PCI related configuration */
+ nxge_setup_hw_pciconfig(nxgep);
+
+ /* Setup the VPD, expansion ROM, or MAC addresses configuration */
+ nxge_setup_hw_vpd_rom_mac(nxgep);
+
+ /*
+ * Read in the hardware (fcode) properties. Use the ndd array
+ * to read each property.
+ */
+ (void) nxge_get_param_soft_properties(nxgep);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " <== nxge_use_cfg_neptune_properties"));
+
+}
+
+/* FWARC 2006/556 */
+static nxge_status_t
+nxge_use_default_dma_config_n2(p_nxge_t nxgep)
+{
+ int ndmas;
+ int nrxgp;
+ uint8_t func;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int *prop_val;
+ uint_t prop_len;
+ int i;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ func = nxgep->function_num;
+ p_cfgp->function_number = func;
+ ndmas = NXGE_TDMA_PER_NIU_PORT;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "tx-dma-channels",
+ (int **)&prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ p_cfgp->start_tdc = prop_val[0];
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2: tdc starts %d "
+ "(#%d)", p_cfgp->start_tdc, prop_len));
+
+ ndmas = prop_val[1];
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2: #tdc %d (#%d)",
+ ndmas, prop_len));
+ ddi_prop_free(prop_val);
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_use_default_dma_config_n2: "
+ "get tx-dma-channels failed"));
+ return (NXGE_DDI_FAILED);
+ }
+
+ p_cfgp->max_tdcs = nxgep->max_tdcs = ndmas;
+ nxgep->tdc_mask = (ndmas - 1);
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
+ "p_cfgp 0x%llx max_tdcs %d nxgep->max_tdcs %d start %d",
+ p_cfgp, p_cfgp->max_tdcs, nxgep->max_tdcs, p_cfgp->start_tdc));
+
+ /* Receive DMA */
+ ndmas = NXGE_RDMA_PER_NIU_PORT;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "rx-dma-channels",
+ (int **)&prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ p_cfgp->start_rdc = prop_val[0];
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2(obp): rdc start %d"
+ " (#%d)", p_cfgp->start_rdc, prop_len));
+
+ ndmas = prop_val[1];
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2(obp):#rdc %d (#%d)",
+ ndmas, prop_len));
+
+ ddi_prop_free(prop_val);
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_use_default_dma_config_n2: "
+ "get rx-dma-channel failed"));
+ return (NXGE_DDI_FAILED);
+ }
+
+ p_cfgp->max_rdcs = nxgep->max_rdcs = ndmas;
+ nxgep->rdc_mask = (ndmas - 1);
+
+ /* Hypervisor: rdc # and group # use the same # !! */
+ p_cfgp->max_grpids = p_cfgp->max_rdcs + p_cfgp->max_tdcs;
+ p_cfgp->start_grpid = 0;
+ p_cfgp->mif_ldvid = p_cfgp->mac_ldvid = p_cfgp->ser_ldvid = 0;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "interrupts",
+ (int **)&prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ /*
+ * For each device assigned, the content of each
+ * interrupts property is its logical device group.
+ *
+ * Assignment of interrupts property is in the
+ * the following order:
+ *
+ * MAC
+ * MIF (if configured)
+ * SYSTEM ERROR (if configured)
+ * first receive channel
+ * next channel......
+ * last receive channel
+ * first transmit channel
+ * next channel......
+ * last transmit channel
+ *
+ * prop_len should be at least for one mac
+ * and total # of rx and tx channels.
+ * Function 0 owns MIF and ERROR
+ */
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2(obp): "
+ "# interrupts %d", prop_len));
+
+ switch (func) {
+ case 0:
+ p_cfgp->ldg_chn_start = 3;
+ p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT0;
+ p_cfgp->mif_ldvid = NXGE_MIF_LD;
+ p_cfgp->ser_ldvid = NXGE_SYS_ERROR_LD;
+
+ break;
+ case 1:
+ p_cfgp->ldg_chn_start = 1;
+ p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT1;
+
+ break;
+ default:
+ status = NXGE_DDI_FAILED;
+ break;
+ }
+
+ if (status != NXGE_OK) {
+ return (status);
+ }
+
+ for (i = 0; i < prop_len; i++) {
+ p_cfgp->ldg[i] = prop_val[i];
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2(obp): "
+ "interrupt #%d, ldg %d",
+ i, p_cfgp->ldg[i]));
+ }
+
+ p_cfgp->max_grpids = prop_len;
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2(obp): %d "
+ "(#%d) maxgrpids %d channel starts %d",
+ p_cfgp->mac_ldvid, i, p_cfgp->max_grpids,
+ p_cfgp->ldg_chn_start));
+ ddi_prop_free(prop_val);
+ } else {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_use_default_dma_config_n2: "
+ "get interrupts failed"));
+ return (NXGE_DDI_FAILED);
+ }
+
+ p_cfgp->max_ldgs = p_cfgp->max_grpids;
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "==> nxge_use_default_dma_config_n2: "
+ "p_cfgp 0x%llx max_rdcs %d nxgep->max_rdcs %d max_grpids %d"
+ "start_grpid %d macid %d mifid %d serrid %d",
+ p_cfgp, p_cfgp->max_rdcs, nxgep->max_rdcs, p_cfgp->max_grpids,
+ p_cfgp->start_grpid,
+ p_cfgp->mac_ldvid, p_cfgp->mif_ldvid, p_cfgp->ser_ldvid));
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
+ "p_cfgp p%p start_ldg %d nxgep->max_ldgs %d",
+ p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs));
+
+
+ /*
+ * RDC groups and the beginning RDC group assigned
+ * to this function.
+ */
+ nrxgp = 2;
+ p_cfgp->max_rdc_grpids = nrxgp;
+ p_cfgp->start_rdc_grpid = (nxgep->function_num * nrxgp);
+
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ "rx-rdc-grps", nrxgp);
+ if (status) {
+ return (NXGE_DDI_FAILED);
+ }
+
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ "rx-rdc-grps-begin", p_cfgp->start_rdc_grpid);
+ if (status) {
+ (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip,
+ "rx-rdc-grps");
+ return (NXGE_DDI_FAILED);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: "
+ "p_cfgp $%p # rdc groups %d start rdc group id %d",
+ p_cfgp, p_cfgp->max_rdc_grpids,
+ p_cfgp->start_rdc_grpid));
+
+ nxge_set_hw_dma_config(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL, "<== nxge_use_default_dma_config_n2"));
+
+ return (status);
+}
+
+static void
+nxge_use_cfg_dma_config(p_nxge_t nxgep)
+{
+ int tx_ndmas, rx_ndmas, nrxgp;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ dev_info_t *dip;
+ p_nxge_param_t param_arr;
+ char *prop;
+ int *prop_val;
+ uint_t prop_len;
+ int status;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_dma_config"));
+ param_arr = nxgep->param_arr;
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ dip = nxgep->dip;
+
+ p_cfgp->function_number = nxgep->function_num;
+
+ prop = param_arr[param_txdma_channels_begin].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_cfgp->start_tdc = *prop_val;
+ ddi_prop_free(prop_val);
+ } else {
+ if (nxgep->nports == 2) {
+ tx_ndmas = (nxgep->function_num * p2_tx_equal[0]);
+ } else {
+ tx_ndmas = (nxgep->function_num * p4_tx_equal[0]);
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, tx_ndmas);
+ p_cfgp->start_tdc = tx_ndmas;
+ }
+
+ prop = param_arr[param_txdma_channels].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ tx_ndmas = *prop_val;
+ ddi_prop_free(prop_val);
+ } else {
+ if (nxgep->nports == 2) {
+ tx_ndmas = p2_tx_equal[0];
+ } else {
+ tx_ndmas = p4_tx_equal[0];
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, tx_ndmas);
+ }
+
+ p_cfgp->max_tdcs = nxgep->max_tdcs = tx_ndmas;
+ nxgep->tdc_mask = (tx_ndmas - 1);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: "
+ "p_cfgp 0x%llx max_tdcs %d nxgep->max_tdcs %d",
+ p_cfgp, p_cfgp->max_tdcs, nxgep->max_tdcs));
+
+
+ prop = param_arr[param_rxdma_channels_begin].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_cfgp->start_rdc = *prop_val;
+ ddi_prop_free(prop_val);
+ } else {
+ if (nxgep->nports == 2) {
+ rx_ndmas = (nxgep->function_num * p2_rx_equal[0]);
+ } else {
+ rx_ndmas = (nxgep->function_num * p4_rx_equal[0]);
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, rx_ndmas);
+ p_cfgp->start_rdc = rx_ndmas;
+ }
+
+ prop = param_arr[param_rxdma_channels].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ rx_ndmas = *prop_val;
+ ddi_prop_free(prop_val);
+ } else {
+ if (nxgep->nports == 2) {
+ rx_ndmas = p2_rx_equal[0];
+ } else {
+ rx_ndmas = p4_rx_equal[0];
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, rx_ndmas);
+ }
+
+ p_cfgp->max_rdcs = nxgep->max_rdcs = rx_ndmas;
+
+ prop = param_arr[param_rdc_grps_start].fcode_name;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_cfgp->start_rdc_grpid = *prop_val;
+ ddi_prop_free(prop_val);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ "==> nxge_use_default_dma_config: "
+ "use property "
+ "start_grpid %d ",
+ p_cfgp->start_grpid));
+ } else {
+ p_cfgp->start_rdc_grpid = nxgep->function_num;
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, p_cfgp->start_rdc_grpid);
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ "==> nxge_use_default_dma_config: "
+ "use default "
+ "start_grpid %d (same as function #)",
+ p_cfgp->start_grpid));
+ }
+
+ prop = param_arr[param_rx_rdc_grps].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ nrxgp = *prop_val;
+ ddi_prop_free(prop_val);
+ } else {
+ nrxgp = 1;
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, nrxgp);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ "==> nxge_use_default_dma_config: "
+ "num_rdc_grpid not found: use def:# of "
+ "rdc groups %d\n", nrxgp));
+ }
+
+ p_cfgp->max_rdc_grpids = nrxgp;
+
+ /*
+ * 2/4 ports have the same hard-wired logical
+ * groups assigned.
+ */
+ p_cfgp->start_ldg = nxgep->function_num * NXGE_LDGRP_PER_4PORTS;
+ p_cfgp->max_ldgs = NXGE_LDGRP_PER_4PORTS;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_default_dma_config: "
+ "p_cfgp 0x%llx max_rdcs %d nxgep->max_rdcs %d max_grpids %d"
+ "start_grpid %d",
+ p_cfgp, p_cfgp->max_rdcs, nxgep->max_rdcs, p_cfgp->max_grpids,
+ p_cfgp->start_grpid));
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: "
+ "p_cfgp 0x%016llx start_ldg %d nxgep->max_ldgs %d "
+ "start_rdc_grpid %d",
+ p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs,
+ p_cfgp->start_rdc_grpid));
+
+/* add code for individual rdc properties */
+ prop = param_arr[param_rxdma_intr_time].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ prop_val, prop_len);
+ }
+ ddi_prop_free(prop_val);
+ }
+ prop = param_arr[param_rxdma_intr_pkts].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
+ &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ prop_val, prop_len);
+ }
+ ddi_prop_free(prop_val);
+ }
+
+ nxge_set_hw_dma_config(nxgep);
+#ifdef lint
+ status = status;
+#endif
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_dma_config"));
+}
+
+
+static void
+nxge_use_cfg_vlan_class_config(p_nxge_t nxgep)
+{
+ uint_t vlan_cnt;
+ int *vlan_cfg_val;
+ int status;
+ p_nxge_param_t param_arr;
+ char *prop;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_vlan_config"));
+ param_arr = nxgep->param_arr;
+ prop = param_arr[param_vlan_2rdc_grp].fcode_name;
+
+ status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &vlan_cfg_val, &vlan_cnt);
+ if (status == DDI_PROP_SUCCESS) {
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ vlan_cfg_val, vlan_cnt);
+ ddi_prop_free(vlan_cfg_val);
+ }
+ nxge_set_hw_vlan_class_config(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_vlan_config"));
+
+}
+
+
+static void
+nxge_use_cfg_mac_class_config(p_nxge_t nxgep)
+{
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ uint_t mac_cnt;
+ int *mac_cfg_val;
+ int status;
+ p_nxge_param_t param_arr;
+ char *prop;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_mac_class_config"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ p_cfgp->start_mac_entry = 0;
+
+ param_arr = nxgep->param_arr;
+ prop = param_arr[param_mac_2rdc_grp].fcode_name;
+
+ switch (nxgep->function_num) {
+ case 0:
+ case 1:
+ /* 10G ports */
+ p_cfgp->max_macs = NXGE_MAX_MACS_XMACS;
+ break;
+ case 2:
+ case 3:
+ /* 1G ports */
+ default:
+ p_cfgp->max_macs = NXGE_MAX_MACS_BMACS;
+ break;
+ }
+
+ p_cfgp->mac_pref = 1;
+ p_cfgp->def_mac_rxdma_grpid = p_cfgp->start_rdc_grpid;
+
+ NXGE_DEBUG_MSG((nxgep, OBP_CTL,
+ "== nxge_use_cfg_mac_class_config: "
+ " mac_pref bit set def_mac_rxdma_grpid %d",
+ p_cfgp->def_mac_rxdma_grpid));
+
+ status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &mac_cfg_val, &mac_cnt);
+ if (status == DDI_PROP_SUCCESS) {
+ if (mac_cnt <= p_cfgp->max_macs)
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ mac_cfg_val,
+ mac_cnt);
+ ddi_prop_free(mac_cfg_val);
+ }
+ nxge_set_hw_mac_class_config(nxgep);
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_mac_class_config"));
+}
+
+
+
+static void
+nxge_use_cfg_class_config(p_nxge_t nxgep)
+{
+ nxge_set_hw_class_config(nxgep);
+}
+
+
+/*ARGSUSED*/
+static void
+nxge_setup_hw_pciconfig(p_nxge_t nxgep)
+{
+ /*
+ * Initialize PCI configuration registers if
+ * required.
+ */
+}
+
+/*ARGSUSED*/
+static void
+nxge_setup_hw_vpd_rom_mac(p_nxge_t nxgep)
+{
+
+}
+
+static void
+nxge_set_rdc_intr_property(p_nxge_t nxgep)
+{
+ int i;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+#ifdef NXGE_CFG_V2
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_param_t param_arr;
+ uint_t rdc_prop_cnt;
+ int *rdc_cfg_val;
+ nxge_rcr_param_t *tout;
+ nxge_rcr_param_t *threshold;
+ char *prop;
+ uint32_t min_val = NXGE_RDC_RCR_TIMEOUT_MIN;
+ uint32_t max_val = NXGE_RDC_RCR_TIMEOUT_MAX;
+#endif
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_rdc_intr_property"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+
+
+ for (i = 0; i < NXGE_MAX_RDCS; i++) {
+ p_dma_cfgp->rcr_timeout[i] = nxge_rcr_timeout;
+ p_dma_cfgp->rcr_threshold[i] = nxge_rcr_threshold;
+ }
+
+#ifdef NXGE_CFG_V2
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ param_arr = nxgep->param_arr;
+ prop = param_arr[param_rxdma_intr_time].fcode_name;
+
+ /*
+ *
+ * Format
+ *
+ * uint32_t array, each array entry specifying the
+ * rdc id and the rcr interrupt blanking parameter
+ *
+ * bit[30] = enable
+ * bit[29] = remove
+ * bits[23-16] = rdc
+ * bits[15-0] = blanking parameter
+ */
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &rdc_cfg_val, &rdc_prop_cnt) ==
+ DDI_PROP_SUCCESS) {
+ tout = (nxge_rcr_param_t *)rdc_cfg_val;
+ for (i = 0; i < rdc_prop_cnt; i++) {
+ if ((tout->rdc < p_cfgp->max_rdcs) &&
+ (tout->cfg_val < NXGE_RDC_RCR_TIMEOUT_MAX) &&
+ (tout->cfg_val >= NXGE_RDC_RCR_TIMEOUT_MIN)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " nxge_rcr param mapping"
+ " rdc %d timeout %d",
+ tout->rdc, tout->cfg_val));
+ p_dma_cfgp->rcr_timeout[tout->rdc] =
+ tout->cfg_val;
+ }
+ tout++;
+ }
+ ddi_prop_free(rdc_cfg_val);
+ }
+
+ prop = param_arr[param_rxdma_intr_pkts].fcode_name;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &rdc_cfg_val, &rdc_prop_cnt) ==
+ DDI_PROP_SUCCESS) {
+ threshold = (nxge_rcr_param_t *)rdc_cfg_val;
+ for (i = 0; i < rdc_prop_cnt; i++) {
+ if ((threshold->rdc < p_cfgp->max_rdcs) &&
+ (threshold->cfg_val < max_val) &&
+ (threshold->cfg_val >= min_val)) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " nxge_rcr param rdc %d"
+ " threshold %x",
+ threshold->rdc,
+ threshold->cfg_val));
+ p_dma_cfgp->rcr_threshold[threshold->rdc] =
+ threshold->cfg_val;
+ }
+ threshold++;
+ }
+ ddi_prop_free(rdc_cfg_val);
+ }
+#endif
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_rdc_intr_property"));
+}
+
+
+/*ARGSUSED*/
+static void
+nxge_set_hw_dma_config(p_nxge_t nxgep)
+{
+ int i, j, rdc, ndmas, ngrps, bitmap, end, st_rdc;
+ int32_t status;
+ uint8_t rdcs_per_grp;
+#ifdef NXGE_CFG_V2
+ int32_t *int_prop_val;
+ uint_t prop_len;
+#endif
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_rdc_grp_t rdc_grp_p;
+ int rdcgrp_cfg = CFG_NOT_SPECIFIED, rx_quick_cfg;
+ char *prop, *prop_val;
+ p_nxge_param_t param_arr;
+ config_token_t token;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_set_hw_dma_config"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ rdc_grp_p = p_dma_cfgp->rdc_grps;
+
+ /* Transmit DMA Channels */
+ bitmap = 0;
+ end = p_cfgp->start_tdc + p_cfgp->max_tdcs;
+ nxgep->ntdc = p_cfgp->max_tdcs;
+ p_dma_cfgp->tx_dma_map = 0;
+ for (i = p_cfgp->start_tdc; i < end; i++) {
+ bitmap |= (1 << i);
+ nxgep->tdc[i - p_cfgp->start_tdc] = (uint8_t)i;
+ }
+
+ p_dma_cfgp->tx_dma_map = bitmap;
+
+ param_arr = nxgep->param_arr;
+
+ /* Assume RDCs are evenly distributed */
+ rx_quick_cfg = param_arr[param_rx_quick_cfg].value;
+ switch (rx_quick_cfg) {
+ case CFG_NOT_SPECIFIED:
+ prop = "rxdma-grp-cfg";
+ status = ddi_prop_lookup_string(DDI_DEV_T_NONE,
+ nxgep->dip, 0,
+ prop,
+ (char **)&prop_val);
+ if (status != DDI_PROP_SUCCESS) {
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL,
+ " property %s not found", prop));
+ rdcgrp_cfg = CFG_L3_DISTRIBUTE;
+ } else {
+ token = nxge_get_config_token(prop_val);
+ switch (token) {
+ case L2_CLASSIFY:
+ break;
+ case CLASSIFY:
+ case L3_CLASSIFY:
+ case L3_DISTRIBUTE:
+ case L3_TCAM:
+ rdcgrp_cfg = CFG_L3_DISTRIBUTE;
+ break;
+ default:
+ rdcgrp_cfg = CFG_L3_DISTRIBUTE;
+ break;
+ }
+ ddi_prop_free(prop_val);
+ }
+ break;
+ case CFG_L3_WEB:
+ case CFG_L3_DISTRIBUTE:
+ case CFG_L2_CLASSIFY:
+ case CFG_L3_TCAM:
+ rdcgrp_cfg = rx_quick_cfg;
+ break;
+ default:
+ rdcgrp_cfg = CFG_L3_DISTRIBUTE;
+ break;
+ }
+
+ /* Receive DMA Channels */
+ st_rdc = p_cfgp->start_rdc;
+ nxgep->nrdc = p_cfgp->max_rdcs;
+
+ for (i = 0; i < p_cfgp->max_rdcs; i++) {
+ nxgep->rdc[i] = i + p_cfgp->start_rdc;
+ }
+
+ switch (rdcgrp_cfg) {
+ case CFG_L3_DISTRIBUTE:
+ case CFG_L3_WEB:
+ case CFG_L3_TCAM:
+ ndmas = p_cfgp->max_rdcs;
+ ngrps = 1;
+ rdcs_per_grp = ndmas/ngrps;
+ break;
+ case CFG_L2_CLASSIFY:
+ ndmas = p_cfgp->max_rdcs / 2;
+ if (p_cfgp->max_rdcs < 2)
+ ndmas = 1;
+ ngrps = 1;
+ rdcs_per_grp = ndmas/ngrps;
+ break;
+ default:
+ ngrps = p_cfgp->max_rdc_grpids;
+ ndmas = p_cfgp->max_rdcs;
+ rdcs_per_grp = ndmas/ngrps;
+ break;
+ }
+
+ for (i = 0; i < ngrps; i++) {
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[i];
+ rdc_grp_p->start_rdc = st_rdc + i * rdcs_per_grp;
+ rdc_grp_p->max_rdcs = rdcs_per_grp;
+
+ /* default to: 0, 1, 2, 3, ...., 0, 1, 2, 3.... */
+ rdc_grp_p->config_method = RDC_TABLE_ENTRY_METHOD_SEQ;
+ rdc = rdc_grp_p->start_rdc;
+ for (j = 0; j < NXGE_MAX_RDCS; j++) {
+ rdc_grp_p->rdc[j] = rdc++;
+ if (rdc == (rdc_grp_p->start_rdc + rdcs_per_grp)) {
+ rdc = rdc_grp_p->start_rdc;
+ }
+ }
+ rdc_grp_p->def_rdc = rdc_grp_p->rdc[0];
+ rdc_grp_p->flag = 1; /* configured */
+ }
+
+ /* default RDC */
+#ifdef NXGE_CFG_V2
+ prop = param_arr[param_default_port_rdc].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_cfgp->def_rdc = (uint8_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ p_cfgp->def_rdc = p_cfgp->start_rdc;
+
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, (int)p_cfgp->def_rdc);
+#ifdef NXGE_DEBUG_ERROR
+ if (status != DDI_PROP_SUCCESS)
+ NXGE_ERROR_MSG((nxgep, NXGE_NOTE,
+ " property %s failed update ", prop));
+#endif
+#else
+ p_cfgp->def_rdc = p_cfgp->start_rdc;
+#endif
+
+ nxgep->def_rdc = p_cfgp->start_rdc;
+
+ /* full 18 byte header ? */
+#ifdef NXGE_CFG_V2
+ prop = param_arr[param_rxdma_full_header].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_dma_cfgp->rcr_full_header = (uint8_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ /* enabled by default */
+ p_dma_cfgp->rcr_full_header = NXGE_RCR_FULL_HEADER;
+
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, (int)p_dma_cfgp->rcr_full_header);
+#else
+ p_dma_cfgp->rcr_full_header = NXGE_RCR_FULL_HEADER;
+#endif
+#ifdef NXGE_CFG_V2
+ prop = param_arr[param_rxdma_drr_weight].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_dma_cfgp->rx_drr_weight = (uint8_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_10G;
+ if (nxgep->function_num > 1)
+ p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_1G;
+
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop,
+ (int)p_dma_cfgp->rx_drr_weight);
+#else
+ p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_10G;
+ if (nxgep->function_num > 1)
+ p_dma_cfgp->rx_drr_weight = PT_DRR_WT_DEFAULT_1G;
+#endif
+
+
+#ifdef NXGE_CFG_V2
+ prop = param_arr[param_rxdma_rbr_size].fcode_name;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_dma_cfgp->rbr_size = (uint32_t)*int_prop_val;
+ if ((p_dma_cfgp->rbr_size <
+ param_arr[param_rxdma_rbr_size].minimum) ||
+ (p_dma_cfgp->rbr_size >
+ param_arr[param_rxdma_rbr_size].maximum))
+ p_dma_cfgp->rbr_size = nxge_rbr_size;
+ ddi_prop_free(int_prop_val);
+ } else {
+ p_dma_cfgp->rbr_size = nxge_rbr_size;
+ }
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, (int)p_dma_cfgp->rbr_size);
+#else
+ p_dma_cfgp->rbr_size = nxge_rbr_size;
+#endif
+
+#ifdef NXGE_CFG_V2
+ prop = param_arr[param_rxdma_rcr_size].fcode_name;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ p_dma_cfgp->rcr_size = (uint32_t)*int_prop_val;
+ if ((p_dma_cfgp->rcr_size <
+ param_arr[param_rxdma_rcr_size].minimum) ||
+ (p_dma_cfgp->rcr_size >
+ param_arr[param_rxdma_rcr_size].maximum))
+ p_dma_cfgp->rcr_size = nxge_rcr_size;
+ ddi_prop_free(int_prop_val);
+ } else {
+ p_dma_cfgp->rcr_size = nxge_rcr_size;
+ }
+
+
+ status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip,
+ prop, (int)p_dma_cfgp->rcr_size);
+#else
+ p_dma_cfgp->rcr_size = nxge_rcr_size;
+#endif
+
+ nxge_set_rdc_intr_property(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_dma_config"));
+
+}
+
+
+
+boolean_t
+nxge_check_rxdma_port_member(p_nxge_t nxgep, uint8_t rdc)
+{
+
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int status = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_rxdma_port_member"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ /* Receive DMA Channels */
+ if (rdc < p_cfgp->max_rdcs)
+ status = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_rxdma_port_member"));
+
+ return (status);
+}
+
+boolean_t
+nxge_check_txdma_port_member(p_nxge_t nxgep, uint8_t tdc)
+{
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int status = B_FALSE;
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_rxdma_port_member"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ /* Receive DMA Channels */
+ if (tdc < p_cfgp->max_tdcs)
+ status = B_TRUE;
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_rxdma_port_member"));
+ return (status);
+}
+
+
+/*ARGSUSED*/
+boolean_t
+nxge_check_rxdma_rdcgrp_member(p_nxge_t nxgep, uint8_t rdc_grp, uint8_t rdc)
+{
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ int status = B_TRUE;
+ p_nxge_rdc_grp_t rdc_grp_p;
+
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
+ " ==> nxge_check_rxdma_rdcgrp_member"));
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " nxge_check_rxdma_rdcgrp_member"
+ " rdc %d group %d",
+ rdc, rdc_grp));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+
+ rdc_grp_p = &p_dma_cfgp->rdc_grps[rdc_grp];
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " max %d ",
+ rdc_grp_p->max_rdcs));
+ if (rdc >= rdc_grp_p->max_rdcs) {
+ status = B_FALSE;
+ }
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
+ " <== nxge_check_rxdma_rdcgrp_member"));
+ return (status);
+}
+
+
+boolean_t
+nxge_check_rdcgrp_port_member(p_nxge_t nxgep, uint8_t rdc_grp)
+{
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ int status = B_TRUE;
+
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, "==> nxge_check_rdcgrp_port_member"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ if (rdc_grp >= p_cfgp->max_rdc_grpids)
+ status = B_FALSE;
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL, " <== nxge_check_rdcgrp_port_member"));
+ return (status);
+
+}
+
+
+static void
+nxge_set_hw_vlan_class_config(p_nxge_t nxgep)
+{
+ int status, i;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_param_t param_arr;
+ uint_t vlan_cnt;
+ int *vlan_cfg_val;
+ nxge_param_map_t *vmap;
+ char *prop;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ uint32_t good_cfg[32];
+ int good_count = 0;
+ nxge_mv_cfg_t *vlan_tbl;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_hw_vlan_config"));
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+
+ param_arr = nxgep->param_arr;
+ prop = param_arr[param_vlan_2rdc_grp].fcode_name;
+
+ /*
+ * By default, VLAN to RDC group mapping is disabled
+ * Need to read HW or .conf properties to find out
+ * if mapping is required
+ *
+ * Format
+ *
+ * uint32_t array, each array entry specifying the
+ * VLAN id and the mapping
+ *
+ * bit[30] = add
+ * bit[29] = remove
+ * bit[28] = preference
+ * bits[23-16] = rdcgrp
+ * bits[15-0] = VLAN ID ( )
+ */
+ for (i = 0; i < NXGE_MAX_VLANS; i++) {
+ p_class_cfgp->vlan_tbl[i].flag = 0;
+ }
+
+ vlan_tbl = (nxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &vlan_cfg_val, &vlan_cnt) ==
+ DDI_PROP_SUCCESS) {
+ for (i = 0; i < vlan_cnt; i++) {
+ vmap = (nxge_param_map_t *)&vlan_cfg_val[i];
+ if ((vmap->param_id) &&
+ (vmap->param_id < NXGE_MAX_VLANS) &&
+ (vmap->map_to < p_cfgp->max_rdc_grpids) &&
+ (vmap->map_to >= (uint8_t)0)) {
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
+ " nxge_vlan_config mapping"
+ " id %d grp %d",
+ vmap->param_id, vmap->map_to));
+
+ good_cfg[good_count] = vlan_cfg_val[i];
+ if (vlan_tbl[vmap->param_id].flag == 0)
+ good_count++;
+ vlan_tbl[vmap->param_id].flag = 1;
+ vlan_tbl[vmap->param_id].rdctbl =
+ vmap->map_to + p_cfgp->start_rdc_grpid;
+ vlan_tbl[vmap->param_id].mpr_npr = vmap->pref;
+
+ }
+ }
+ ddi_prop_free(vlan_cfg_val);
+ if (good_count != vlan_cnt) {
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ (int *)good_cfg, good_count);
+ }
+ }
+#ifdef lint
+ status = status;
+#endif
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_vlan_config"));
+}
+
+static void
+nxge_set_hw_mac_class_config(p_nxge_t nxgep)
+{
+ int status, i;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_param_t param_arr;
+ uint_t mac_cnt;
+ int *mac_cfg_val;
+ nxge_param_map_t *mac_map;
+ char *prop;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ int good_count = 0;
+ int good_cfg[NXGE_MAX_MACS];
+ nxge_mv_cfg_t *mac_host_info;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_set_hw_mac_config"));
+
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+ mac_host_info = (nxge_mv_cfg_t *)&p_class_cfgp->mac_host_info[0];
+
+ param_arr = nxgep->param_arr;
+ prop = param_arr[param_mac_2rdc_grp].fcode_name;
+
+ for (i = 0; i < NXGE_MAX_MACS; i++) {
+ p_class_cfgp->mac_host_info[i].flag = 0;
+ }
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &mac_cfg_val, &mac_cnt) ==
+ DDI_PROP_SUCCESS) {
+ for (i = 0; i < mac_cnt; i++) {
+ mac_map = (nxge_param_map_t *)&mac_cfg_val[i];
+ if ((mac_map->param_id < p_cfgp->max_macs) &&
+ (mac_map->map_to < p_cfgp->max_rdc_grpids) &&
+ (mac_map->map_to >= (uint8_t)0)) {
+ NXGE_DEBUG_MSG((nxgep, CFG2_CTL,
+ " nxge_mac_config mapping"
+ " id %d grp %d",
+ mac_map->param_id,
+ mac_map->map_to));
+
+ mac_host_info[mac_map->param_id].mpr_npr =
+ mac_map->pref;
+ mac_host_info[mac_map->param_id].rdctbl =
+ mac_map->map_to +
+ p_cfgp->start_rdc_grpid;
+ good_cfg[good_count] = mac_cfg_val[i];
+ if (mac_host_info[mac_map->param_id].flag == 0)
+ good_count++;
+ mac_host_info[mac_map->param_id].flag = 1;
+ }
+ }
+ ddi_prop_free(mac_cfg_val);
+ if (good_count != mac_cnt) {
+ status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
+ nxgep->dip, prop,
+ good_cfg, good_count);
+ }
+
+ }
+#ifdef lint
+ status = status;
+#endif
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_mac_config"));
+}
+
+
+static void
+nxge_set_hw_class_config(p_nxge_t nxgep)
+{
+ int i;
+ p_nxge_param_t param_arr;
+ int *int_prop_val;
+ uint32_t cfg_value;
+ char *prop;
+ p_nxge_class_pt_cfg_t p_class_cfgp;
+ int start_prop, end_prop;
+ uint_t prop_cnt;
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_hw_class_config"));
+
+ p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
+
+ param_arr = nxgep->param_arr;
+
+ start_prop = param_class_opt_ip_usr4;
+ end_prop = param_class_opt_ipv6_sctp;
+
+ for (i = start_prop; i <= end_prop; i++) {
+ prop = param_arr[i].fcode_name;
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
+ 0, prop,
+ &int_prop_val, &prop_cnt) ==
+ DDI_PROP_SUCCESS) {
+ cfg_value = (uint32_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ cfg_value = (uint32_t)param_arr[i].value;
+ }
+ p_class_cfgp->class_cfg[i - start_prop] = cfg_value;
+ }
+
+ prop = param_arr[param_h1_init_value].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_cnt) ==
+ DDI_PROP_SUCCESS) {
+ cfg_value = (uint32_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ cfg_value = (uint32_t)param_arr[param_h1_init_value].value;
+ }
+
+ p_class_cfgp->init_h1 = (uint32_t)cfg_value;
+
+ prop = param_arr[param_h2_init_value].fcode_name;
+
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop,
+ &int_prop_val, &prop_cnt) ==
+ DDI_PROP_SUCCESS) {
+ cfg_value = (uint32_t)*int_prop_val;
+ ddi_prop_free(int_prop_val);
+ } else {
+ cfg_value = (uint32_t)param_arr[param_h2_init_value].value;
+ }
+
+ p_class_cfgp->init_h2 = (uint16_t)cfg_value;
+
+ NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_hw_class_config"));
+}
+
+/*ARGSUSED*/
+nxge_status_t
+nxge_ldgv_init_n2(p_nxge_t nxgep, int *navail_p, int *nrequired_p)
+{
+ int i, maxldvs, maxldgs, start, end, nldvs;
+ int ldv, endldg;
+#ifdef S11
+ int ldg;
+#endif
+ uint8_t func;
+ uint8_t channel;
+ uint8_t chn_start;
+ boolean_t own_sys_err = B_FALSE, own_fzc = B_FALSE;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldg_t ldgp, ptr;
+ p_nxge_ldv_t ldvp;
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2"));
+ if (!*navail_p) {
+ *nrequired_p = 0;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_ldgv_init:no avail"));
+ return (NXGE_ERROR);
+ }
+
+ /*
+ * N2/NIU: one logical device owns one logical group.
+ * and each device/group will be assigned
+ * one vector by Hypervisor.
+ */
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+ maxldgs = p_cfgp->max_ldgs;
+ if (!maxldgs) {
+ /* No devices configured. */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_init_n2: "
+ "no logical groups configured."));
+ return (NXGE_ERROR);
+ } else {
+ maxldvs = maxldgs + 1;
+ }
+
+ /*
+ * If function zero instance, it needs to handle the
+ * system and MIF error interrupts.
+ * MIF interrupt may not be needed for N2/NIU.
+ */
+ func = nxgep->function_num;
+ if (func == 0) {
+ own_sys_err = B_TRUE;
+ if (!p_cfgp->ser_ldvid) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ldgv_init_n2: func 0, ERR ID not set!"));
+ }
+ /* MIF interrupt */
+ if (!p_cfgp->mif_ldvid) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_ldgv_init_n2: func 0, MIF ID not set!"));
+ }
+ }
+
+ /*
+ * Assume single partition, each function owns mac.
+ */
+ if (!nxge_use_partition) {
+ own_fzc = B_TRUE;
+ }
+
+ ldgvp = nxgep->ldgvp;
+ if (ldgvp == NULL) {
+ ldgvp = KMEM_ZALLOC(sizeof (nxge_ldgv_t), KM_SLEEP);
+ nxgep->ldgvp = ldgvp;
+ ldgvp->maxldgs = (uint8_t)maxldgs;
+ ldgvp->maxldvs = (uint8_t)maxldvs;
+ ldgp = ldgvp->ldgp = KMEM_ZALLOC(sizeof (nxge_ldg_t) * maxldgs,
+ KM_SLEEP);
+ ldvp = ldgvp->ldvp = KMEM_ZALLOC(sizeof (nxge_ldv_t) * maxldvs,
+ KM_SLEEP);
+ } else {
+ ldgp = ldgvp->ldgp;
+ ldvp = ldgvp->ldvp;
+ }
+
+ ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
+ ldgvp->tmres = NXGE_TIMER_RESO;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d",
+ maxldvs, maxldgs));
+ /* logical start_ldg is ldv */
+#if S11
+ ldg = p_cfgp->start_ldg;
+#endif
+ ptr = ldgp;
+ for (i = 0; i < maxldgs; i++) {
+ ptr->func = func;
+ ptr->arm = B_TRUE;
+ ptr->vldg_index = (uint8_t)i;
+ ptr->ldg_timer = NXGE_TIMER_LDG;
+#if S11
+ ptr->ldg = ldg++;
+#endif
+ ptr->ldg = p_cfgp->ldg[i];
+ ptr->sys_intr_handler = nxge_intr;
+ ptr->nldvs = 0;
+ ptr->ldvp = NULL;
+ ptr->nxgep = nxgep;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d "
+ "ldg %d ldgptr $%p",
+ maxldvs, maxldgs, ptr->ldg, ptr));
+ ptr++;
+ }
+
+#ifdef S11
+ ldg = p_cfgp->start_ldg;
+#endif
+ endldg = NXGE_INT_MAX_LDG;
+ nldvs = 0;
+ ldgvp->nldvs = 0;
+ ldgp->ldvp = NULL;
+ *nrequired_p = 0;
+
+ /*
+ * logical device group table is organized in
+ * the following order (same as what interrupt
+ * property has).
+ * function 0: owns MAC, MIF, error, rx, tx.
+ * function 1: owns MAC, rx, tx.
+ */
+
+ if (own_fzc && p_cfgp->mac_ldvid) {
+ /* Each function should own MAC interrupt */
+ ldv = p_cfgp->mac_ldvid;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_mac = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_mac_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->nxgep = nxgep;
+#if S11
+ if (!func) {
+ ldgp->ldg = NXGE_N2_MAC_0_LDG;
+ } else {
+ ldgp->ldg = NXGE_N2_MAC_1_LDG;
+ }
+#endif
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2(mac): maxldvs %d ldv %d "
+ "ldg %d ldgptr $%p ldvptr $%p",
+ maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ if (own_fzc && p_cfgp->mif_ldvid) {
+ ldv = p_cfgp->mif_ldvid;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_mif = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_mif_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->nxgep = nxgep;
+#ifdef S11
+ ldgp->ldg = NXGE_N2_MIF_LDG;
+#endif
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2(mif): maxldvs %d ldv %d "
+ "ldg %d ldgptr $%p ldvptr $%p",
+ maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ ldv = NXGE_SYS_ERROR_LD;
+ ldvp->use_timer = B_TRUE;
+ if (own_sys_err && p_cfgp->ser_ldvid) {
+ ldv = p_cfgp->ser_ldvid;
+#ifdef NXGE_SYSERR_USE_INT
+ ldvp->use_timer = B_FALSE;
+#else
+ ldvp->use_timer = B_TRUE;
+#endif
+ ldvp->use_timer = B_FALSE;
+
+ /*
+ * Unmask the system interrupt states.
+ */
+ (void) nxge_fzc_sys_err_mask_set(nxgep, SYS_ERR_SMX_MASK |
+ SYS_ERR_IPP_MASK | SYS_ERR_TXC_MASK |
+ SYS_ERR_ZCP_MASK);
+ }
+
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_syserr = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_syserr_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->nxgep = nxgep;
+ ldgvp->ldvp_syserr = ldvp;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2(syserr): maxldvs %d ldv %d "
+ "ldg %d ldgptr $%p ldvptr p%p",
+ maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
+
+ if (ldvp->use_timer == B_FALSE) {
+ (void) nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ } else {
+ ldvp++;
+ }
+
+ nldvs++;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
+ "(before rx) func %d nldvs %d navail %d nrequired %d",
+ func, nldvs, *navail_p, *nrequired_p));
+
+ /*
+ * Receive DMA channels.
+ */
+ channel = p_cfgp->start_rdc;
+ start = p_cfgp->start_rdc + NXGE_RDMA_LD_START;
+ end = start + p_cfgp->max_rdcs;
+ chn_start = p_cfgp->ldg_chn_start;
+ /*
+ * Start with RDC to configure logical devices for each group.
+ */
+ for (i = 0, ldv = start; ldv < end; i++, ldv++, chn_start++) {
+ ldvp->is_rxdma = B_TRUE;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->channel = channel++;
+ ldvp->vdma_index = (uint8_t)i;
+ ldvp->ldv_intr_handler = nxge_rx_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->nxgep = nxgep;
+#ifdef S11
+ ldgp->ldg = ((NXGE_N2_RXDMA_START_LDG + i) +
+ (func * NXGE_N2_LDG_GAP));
+#endif
+ ldgp->ldg = p_cfgp->ldg[chn_start];
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2(rx%d): maxldvs %d ldv %d "
+ "ldg %d ldgptr 0x%016llx ldvptr 0x%016llx",
+ i, maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
+ "func %d nldvs %d navail %d nrequired %d",
+ func, nldvs, *navail_p, *nrequired_p));
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
+ "func %d nldvs %d navail %d nrequired %d ldgp 0x%llx "
+ "ldvp 0x%llx",
+ func, nldvs, *navail_p, *nrequired_p, ldgp, ldvp));
+ /*
+ * Transmit DMA channels.
+ */
+ channel = p_cfgp->start_tdc;
+ start = p_cfgp->start_tdc + NXGE_TDMA_LD_START;
+ end = start + p_cfgp->max_tdcs;
+ for (i = 0, ldv = start; ldv < end; i++, ldv++, chn_start++) {
+ ldvp->is_txdma = B_TRUE;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->channel = channel++;
+ ldvp->vdma_index = (uint8_t)i;
+ ldvp->ldv_intr_handler = nxge_tx_intr;
+ ldvp->ldv_ldf_masks = 0;
+#ifdef S11
+ ldgp->ldg = ((NXGE_N2_TXDMA_START_LDG + i) +
+ (func * NXGE_N2_LDG_GAP));
+#endif
+ ldgp->ldg = p_cfgp->ldg[chn_start];
+ ldvp->nxgep = nxgep;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init_n2(tx%d): maxldvs %d ldv %d "
+ "ldg %d ldgptr 0x%016llx ldvptr 0x%016llx",
+ i, maxldvs, ldv, ldgp->ldg, ldgp, ldvp));
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ ldgvp->ldg_intrs = *nrequired_p;
+ ldgvp->nldvs = (uint8_t)nldvs;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init_n2: "
+ "func %d nldvs %d maxgrps %d navail %d nrequired %d",
+ func, nldvs, maxldgs, *navail_p, *nrequired_p));
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_init_n2"));
+
+ return (status);
+}
+
+/*
+ * Interrupts related interface functions.
+ */
+nxge_status_t
+nxge_ldgv_init(p_nxge_t nxgep, int *navail_p, int *nrequired_p)
+{
+ int i, maxldvs, maxldgs, start, end, nldvs;
+ int ldv, ldg, endldg, ngrps;
+ uint8_t func;
+ uint8_t channel;
+ boolean_t own_sys_err = B_FALSE, own_fzc = B_FALSE;
+ p_nxge_dma_pt_cfg_t p_dma_cfgp;
+ p_nxge_hw_pt_cfg_t p_cfgp;
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldg_t ldgp, ptr;
+ p_nxge_ldv_t ldvp;
+ nxge_status_t status = NXGE_OK;
+
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init"));
+ if (!*navail_p) {
+ *nrequired_p = 0;
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_ldgv_init:no avail"));
+ return (NXGE_ERROR);
+ }
+ p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
+ p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
+
+ nldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
+
+ /*
+ * If function zero instance, it needs to handle the
+ * system error interrupts.
+ */
+ func = nxgep->function_num;
+ if (func == 0) {
+ nldvs++;
+ own_sys_err = B_TRUE;
+ } else {
+ /* use timer */
+ nldvs++;
+ }
+
+ /*
+ * Assume single partition, each function owns mac.
+ */
+ if (!nxge_use_partition) {
+ /* mac */
+ nldvs++;
+ /* MIF */
+ nldvs++;
+ own_fzc = B_TRUE;
+ }
+
+ maxldvs = nldvs;
+ maxldgs = p_cfgp->max_ldgs;
+ if (!maxldvs || !maxldgs) {
+ /* No devices configured. */
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_init: "
+ "no logical devices or groups configured."));
+ return (NXGE_ERROR);
+ }
+ ldgvp = nxgep->ldgvp;
+ if (ldgvp == NULL) {
+ ldgvp = KMEM_ZALLOC(sizeof (nxge_ldgv_t), KM_SLEEP);
+ nxgep->ldgvp = ldgvp;
+ ldgvp->maxldgs = (uint8_t)maxldgs;
+ ldgvp->maxldvs = (uint8_t)maxldvs;
+ ldgp = ldgvp->ldgp = KMEM_ZALLOC(sizeof (nxge_ldg_t) * maxldgs,
+ KM_SLEEP);
+ ldvp = ldgvp->ldvp = KMEM_ZALLOC(sizeof (nxge_ldv_t) * maxldvs,
+ KM_SLEEP);
+ }
+
+ ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
+ ldgvp->tmres = NXGE_TIMER_RESO;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d",
+ maxldvs, maxldgs, nldvs));
+ ldg = p_cfgp->start_ldg;
+ ptr = ldgp;
+ for (i = 0; i < maxldgs; i++) {
+ ptr->func = func;
+ ptr->arm = B_TRUE;
+ ptr->vldg_index = (uint8_t)i;
+ ptr->ldg_timer = NXGE_TIMER_LDG;
+ ptr->ldg = ldg++;
+ ptr->sys_intr_handler = nxge_intr;
+ ptr->nldvs = 0;
+ ptr->nxgep = nxgep;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_ldgv_init: maxldvs %d maxldgs %d ldg %d",
+ maxldvs, maxldgs, ptr->ldg));
+ ptr++;
+ }
+
+ ldg = p_cfgp->start_ldg;
+ if (maxldgs > *navail_p) {
+ ngrps = *navail_p;
+ } else {
+ ngrps = maxldgs;
+ }
+ endldg = ldg + ngrps;
+
+ /*
+ * Receive DMA channels.
+ */
+ channel = p_cfgp->start_rdc;
+ start = p_cfgp->start_rdc + NXGE_RDMA_LD_START;
+ end = start + p_cfgp->max_rdcs;
+ nldvs = 0;
+ ldgvp->nldvs = 0;
+ ldgp->ldvp = NULL;
+ *nrequired_p = 0;
+
+ /*
+ * Start with RDC to configure logical devices for each group.
+ */
+ for (i = 0, ldv = start; ldv < end; i++, ldv++) {
+ ldvp->is_rxdma = B_TRUE;
+ ldvp->ldv = (uint8_t)ldv;
+ /* If non-seq needs to change the following code */
+ ldvp->channel = channel++;
+ ldvp->vdma_index = (uint8_t)i;
+ ldvp->ldv_intr_handler = nxge_rx_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->use_timer = B_FALSE;
+ ldvp->nxgep = nxgep;
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+ /*
+ * Transmit DMA channels.
+ */
+ channel = p_cfgp->start_tdc;
+ start = p_cfgp->start_tdc + NXGE_TDMA_LD_START;
+ end = start + p_cfgp->max_tdcs;
+ for (i = 0, ldv = start; ldv < end; i++, ldv++) {
+ ldvp->is_txdma = B_TRUE;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->channel = channel++;
+ ldvp->vdma_index = (uint8_t)i;
+ ldvp->ldv_intr_handler = nxge_tx_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->use_timer = B_FALSE;
+ ldvp->nxgep = nxgep;
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ if (own_fzc) {
+ ldv = NXGE_MIF_LD;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_mif = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_mif_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->use_timer = B_FALSE;
+ ldvp->nxgep = nxgep;
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ /*
+ * MAC port (function zero control)
+ */
+ if (own_fzc) {
+ ldvp->is_mac = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_mac_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldv = func + NXGE_MAC_LD_START;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->use_timer = B_FALSE;
+ ldvp->nxgep = nxgep;
+ nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init: "
+ "func %d nldvs %d navail %d nrequired %d",
+ func, nldvs, *navail_p, *nrequired_p));
+ /*
+ * Function 0 owns system error interrupts.
+ */
+ if (own_sys_err) {
+ ldv = NXGE_SYS_ERROR_LD;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_syserr = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_syserr_intr;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->nxgep = nxgep;
+#ifdef NXGE_SYSERR_USE_INT
+ ldvp->use_timer = B_FALSE;
+#else
+ ldvp->use_timer = B_TRUE;
+#endif
+ ldgvp->ldvp_syserr = ldvp;
+ /*
+ * Unmask the system interrupt states.
+ */
+ (void) nxge_fzc_sys_err_mask_set(nxgep, SYS_ERR_SMX_MASK |
+ SYS_ERR_IPP_MASK | SYS_ERR_TXC_MASK |
+ SYS_ERR_ZCP_MASK);
+
+ (void) nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ } else {
+ ldv = NXGE_SYS_ERROR_LD;
+ ldvp->ldv = (uint8_t)ldv;
+ ldvp->is_syserr = B_TRUE;
+ ldvp->ldv_intr_handler = nxge_syserr_intr;
+ ldvp->nxgep = nxgep;
+ ldvp->ldv_ldf_masks = 0;
+ ldvp->use_timer = B_TRUE;
+ ldgvp->ldvp_syserr = ldvp;
+ (void) nxge_ldgv_setup(&ldgp, &ldvp, ldv, endldg, nrequired_p);
+ nldvs++;
+ }
+
+ ldgvp->ldg_intrs = *nrequired_p;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_init: "
+ "func %d nldvs %d navail %d nrequired %d",
+ func, nldvs, *navail_p, *nrequired_p));
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_init"));
+
+ return (status);
+}
+
+nxge_status_t
+nxge_ldgv_uninit(p_nxge_t nxgep)
+{
+ p_nxge_ldgv_t ldgvp;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_ldgv_uninit"));
+ ldgvp = nxgep->ldgvp;
+ if (ldgvp == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_ldgv_uninit: "
+ "no logical group configured."));
+ return (NXGE_OK);
+ }
+
+ if (ldgvp->ldgp) {
+ KMEM_FREE(ldgvp->ldgp, sizeof (nxge_ldg_t) * ldgvp->maxldgs);
+ }
+ if (ldgvp->ldvp) {
+ KMEM_FREE(ldgvp->ldvp, sizeof (nxge_ldv_t) * ldgvp->maxldvs);
+ }
+
+ KMEM_FREE(ldgvp, sizeof (nxge_ldgv_t));
+ nxgep->ldgvp = NULL;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_ldgv_uninit"));
+
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_intr_ldgv_init(p_nxge_t nxgep)
+{
+ nxge_status_t status = NXGE_OK;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_ldgv_init"));
+ /*
+ * Configure the logical device group numbers, state vectors
+ * and interrupt masks for each logical device.
+ */
+ status = nxge_fzc_intr_init(nxgep);
+
+ /*
+ * Configure logical device masks and timers.
+ */
+ status = nxge_intr_mask_mgmt(nxgep);
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_ldgv_init"));
+ return (status);
+}
+
+nxge_status_t
+nxge_intr_mask_mgmt(p_nxge_t nxgep)
+{
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldg_t ldgp;
+ p_nxge_ldv_t ldvp;
+ npi_handle_t handle;
+ int i, j;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_mask_mgmt"));
+
+ if ((ldgvp = nxgep->ldgvp) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt: Null ldgvp"));
+ return (NXGE_ERROR);
+ }
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ ldgp = ldgvp->ldgp;
+ ldvp = ldgvp->ldvp;
+ if (ldgp == NULL || ldvp == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt: Null ldgp or ldvp"));
+ return (NXGE_ERROR);
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs));
+ /* Initialize masks. */
+ if (nxgep->niu_type != N2_NIU) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt(Neptune): # intrs %d ",
+ ldgvp->ldg_intrs));
+ for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt(Neptune): # ldv %d "
+ "in group %d", ldgp->nldvs, ldgp->ldg));
+ for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt: set ldv # %d "
+ "for ldg %d", ldvp->ldv, ldgp->ldg));
+ rs = npi_intr_mask_set(handle, ldvp->ldv,
+ ldvp->ldv_ldf_masks);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt: "
+ "set mask failed "
+ " rs 0x%x ldv %d mask 0x%x",
+ rs, ldvp->ldv,
+ ldvp->ldv_ldf_masks));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt: "
+ "set mask OK "
+ " rs 0x%x ldv %d mask 0x%x",
+ rs, ldvp->ldv,
+ ldvp->ldv_ldf_masks));
+ }
+ }
+ }
+
+ ldgp = ldgvp->ldgp;
+ /* Configure timer and arm bit */
+ for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
+ rs = npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ ldgp->arm, ldgp->ldg_timer);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt: "
+ "set timer failed "
+ " rs 0x%x dg %d timer 0x%x",
+ rs, ldgp->ldg, ldgp->ldg_timer));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt: "
+ "set timer OK "
+ " rs 0x%x ldg %d timer 0x%x",
+ rs, ldgp->ldg, ldgp->ldg_timer));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_mask_mgmt"));
+ return (NXGE_OK);
+}
+
+nxge_status_t
+nxge_intr_mask_mgmt_set(p_nxge_t nxgep, boolean_t on)
+{
+ p_nxge_ldgv_t ldgvp;
+ p_nxge_ldg_t ldgp;
+ p_nxge_ldv_t ldvp;
+ npi_handle_t handle;
+ int i, j;
+ npi_status_t rs = NPI_SUCCESS;
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set (%d)", on));
+
+ if (nxgep->niu_type == N2_NIU) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "<== nxge_intr_mask_mgmt_set (%d) not set (N2/NIU)",
+ on));
+ return (NXGE_ERROR);
+
+ }
+ if ((ldgvp = nxgep->ldgvp) == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_intr_mask_mgmt_set: Null ldgvp"));
+ return (NXGE_ERROR);
+ }
+ handle = NXGE_DEV_NPI_HANDLE(nxgep);
+ ldgp = ldgvp->ldgp;
+ ldvp = ldgvp->ldvp;
+ if (ldgp == NULL || ldvp == NULL) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt_set: Null ldgp or ldvp"));
+ return (NXGE_ERROR);
+ }
+
+ /* set masks. */
+ for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set: flag %d ldg %d"
+ "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs));
+ for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set: "
+ "for %d %d flag %d", i, j, on));
+ if (on) {
+ ldvp->ldv_ldf_masks = 0;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set: "
+ "ON mask off"));
+ } else if (!on) {
+ ldvp->ldv_ldf_masks = (uint8_t)LD_IM1_MASK;
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set:mask on"));
+ }
+ rs = npi_intr_mask_set(handle, ldvp->ldv,
+ ldvp->ldv_ldf_masks);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "==> nxge_intr_mask_mgmt_set: "
+ "set mask failed "
+ " rs 0x%x ldv %d mask 0x%x",
+ rs, ldvp->ldv, ldvp->ldv_ldf_masks));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set: flag %d"
+ "set mask OK "
+ " ldv %d mask 0x%x",
+ on, ldvp->ldv, ldvp->ldv_ldf_masks));
+ }
+ }
+
+ ldgp = ldgvp->ldgp;
+ /* set the arm bit */
+ for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
+ if (on && !ldgp->arm) {
+ ldgp->arm = B_TRUE;
+ } else if (!on && ldgp->arm) {
+ ldgp->arm = B_FALSE;
+ }
+ rs = npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
+ ldgp->arm, ldgp->ldg_timer);
+ if (rs != NPI_SUCCESS) {
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "<== nxge_intr_mask_mgmt_set: "
+ "set timer failed "
+ " rs 0x%x ldg %d timer 0x%x",
+ rs, ldgp->ldg, ldgp->ldg_timer));
+ return (NXGE_ERROR | rs);
+ }
+ NXGE_DEBUG_MSG((nxgep, INT_CTL,
+ "==> nxge_intr_mask_mgmt_set: OK (flag %d) "
+ "set timer "
+ " ldg %d timer 0x%x",
+ on, ldgp->ldg, ldgp->ldg_timer));
+ }
+
+ NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_mask_mgmt_set"));
+ return (NXGE_OK);
+}
+
+void
+nxge_get_mac_addr_properties(p_nxge_t nxgep)
+{
+ uchar_t *prop_val;
+ uint_t prop_len;
+ uint_t i;
+ uint8_t func_num;
+ uint8_t num_macs;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_get_mac_addr_properties "));
+
+#if defined(_BIG_ENDIAN)
+ /*
+ * Get the ethernet address.
+ */
+ (void) localetheraddr((struct ether_addr *)NULL, &nxgep->ouraddr);
+
+ /*
+ * Check if it is an adapter with its own local mac address
+ * If it is present, override the system mac address.
+ */
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "local-mac-address", &prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ if (prop_len == ETHERADDRL) {
+ nxgep->factaddr = *(p_ether_addr_t)prop_val;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Local mac address = "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ prop_val[0], prop_val[1], prop_val[2],
+ prop_val[3], prop_val[4], prop_val[5]));
+ }
+ ddi_prop_free(prop_val);
+ }
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "local-mac-address?", &prop_val,
+ &prop_len) == DDI_PROP_SUCCESS) {
+ if (strncmp("true", (caddr_t)prop_val,
+ (size_t)prop_len) == 0) {
+ nxgep->ouraddr = nxgep->factaddr;
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+ "Using local MAC address"));
+ }
+ ddi_prop_free(prop_val);
+ } else {
+ nxgep->ouraddr = nxgep->factaddr;
+ }
+#else
+ (void) nxge_espc_mac_addrs_get(nxgep);
+ nxgep->ouraddr = nxgep->factaddr;
+#endif
+
+ func_num = nxgep->function_num;
+
+ /* NIU does not need max_num_mmac */
+ if (nxgep->niu_type == NEPTUNE || nxgep->niu_type == NEPTUNE_2) {
+ if (nxge_espc_num_macs_get(nxgep, &num_macs) == NXGE_OK) {
+ nxgep->nxge_mmac_info.max_num_mmac = num_macs;
+ } else {
+ NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
+ "nxge_get_mac_addr_properties, espc access failed"));
+ }
+ }
+
+ /*
+ * Note: mac-addresses of n2-niu is the list of mac addresses
+ * for a port. #mac-addresses stored in Neptune's SEEPROM is
+ * the total number of MAC addresses allocated for a board.
+ */
+ if (nxgep->niu_type == N2_NIU) {
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "mac-addresses", &prop_val, &prop_len) ==
+ DDI_PROP_SUCCESS) {
+ /*
+ * XAUI may have up to 18 MACs, more than the XMAC can
+ * use (1 unique MAC plus 16 alternate MACs)
+ */
+ nxgep->nxge_mmac_info.num_mmac = prop_len / 6;
+ if (nxgep->nxge_mmac_info.num_mmac >
+ XMAC_MAX_ALT_ADDR_ENTRY + 1) {
+ nxgep->nxge_mmac_info.num_mmac =
+ XMAC_MAX_ALT_ADDR_ENTRY + 1;
+ }
+ ddi_prop_free(prop_val);
+ }
+ } else {
+ nxgep->nxge_mmac_info.num_mmac
+ = nxgep->nxge_mmac_info.max_num_mmac >>
+ (nxgep->nports >> 1);
+ }
+
+ for (i = 0; i < nxgep->nxge_mmac_info.num_mmac - 1; ++i) {
+ /* Initialze all mac addr. to "AVAILABLE" state */
+ nxgep->nxge_mmac_info.rsv_mmac[i] = B_FALSE;
+ /*
+ * XMAC: Disable alter MAC address comparison only
+ * (XMAC's unique MAC comparison is always
+ * enabled.
+ * BMAC: (Neptune only) Disable both unique and
+ * alter MAC address comparison
+ */
+ (void) npi_mac_altaddr_disable(nxgep->npi_handle,
+ NXGE_GET_PORT_NUM(func_num), i);
+ }
+
+ /*
+ * Initialize alt. mac addr. in the mac pool
+ */
+ (void) nxge_init_mmac(nxgep);
+}
+
+void
+nxge_get_xcvr_properties(p_nxge_t nxgep)
+{
+ uchar_t *prop_val;
+ uint_t prop_len;
+
+ NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_get_xcvr_properties"));
+
+ /*
+ * Read the type of physical layer interface being used.
+ */
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "phy-type", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ if (strncmp("pcs", (caddr_t)prop_val, (size_t)prop_len) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ } else {
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ }
+ ddi_prop_free(prop_val);
+ } else if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
+ "phy-interface", &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
+ if (strncmp("pcs", (caddr_t)prop_val, (size_t)prop_len) == 0) {
+ nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
+ } else {
+ nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
+ }
+ ddi_prop_free(prop_val);
+ }
+}
+
+/*
+ * Static functions start here.
+ */
+static void
+nxge_ldgv_setup(p_nxge_ldg_t *ldgp, p_nxge_ldv_t *ldvp, uint8_t ldv,
+ uint8_t endldg, int *ngrps)
+{
+ NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup"));
+ /* Assign the group number for each device. */
+ (*ldvp)->ldg_assigned = (*ldgp)->ldg;
+ (*ldvp)->ldgp = *ldgp;
+ (*ldvp)->ldv = ldv;
+
+ NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup: "
+ "ldv %d endldg %d ldg %d, ldvp $%p",
+ ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
+
+ (*ldgp)->nldvs++;
+ if ((*ldgp)->ldg == (endldg - 1)) {
+ if ((*ldgp)->ldvp == NULL) {
+ (*ldgp)->ldvp = *ldvp;
+ *ngrps += 1;
+ NXGE_DEBUG_MSG((NULL, INT_CTL,
+ "==> nxge_ldgv_setup: ngrps %d", *ngrps));
+ }
+ NXGE_DEBUG_MSG((NULL, INT_CTL,
+ "==> nxge_ldgv_setup: ldvp $%p ngrps %d",
+ *ldvp, *ngrps));
+ ++*ldvp;
+ } else {
+ (*ldgp)->ldvp = *ldvp;
+ *ngrps += 1;
+ NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup(done): "
+ "ldv %d endldg %d ldg %d, ldvp $%p",
+ ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
+ (*ldvp) = ++*ldvp;
+ (*ldgp) = ++*ldgp;
+ NXGE_DEBUG_MSG((NULL, INT_CTL,
+ "==> nxge_ldgv_setup: new ngrps %d", *ngrps));
+ }
+
+ NXGE_DEBUG_MSG((NULL, INT_CTL, "==> nxge_ldgv_setup: "
+ "ldv %d ldvp $%p endldg %d ngrps %d",
+ ldv, ldvp, endldg, *ngrps));
+
+ NXGE_DEBUG_MSG((NULL, INT_CTL, "<== nxge_ldgv_setup"));
+}
+
+/*
+ * Note: This function assume the following distribution of mac
+ * addresses among 4 ports in neptune:
+ *
+ * -------------
+ * 0| |0 - local-mac-address for fn 0
+ * -------------
+ * 1| |1 - local-mac-address for fn 1
+ * -------------
+ * 2| |2 - local-mac-address for fn 2
+ * -------------
+ * 3| |3 - local-mac-address for fn 3
+ * -------------
+ * | |4 - Start of alt. mac addr. for fn 0
+ * | |
+ * | |
+ * | |10
+ * --------------
+ * | |11 - Start of alt. mac addr. for fn 1
+ * | |
+ * | |
+ * | |17
+ * --------------
+ * | |18 - Start of alt. mac addr. for fn 2
+ * | |
+ * | |
+ * | |24
+ * --------------
+ * | |25 - Start of alt. mac addr. for fn 3
+ * | |
+ * | |
+ * | |31
+ * --------------
+ *
+ * For N2/NIU the mac addresses is from XAUI card.
+ */
+
+static void
+nxge_init_mmac(p_nxge_t nxgep)
+{
+ int i;
+ uint8_t func_num;
+ uint16_t *base_mmac_addr;
+ uint32_t first_alt_mac_ls4b;
+ uint16_t *mmac_addr;
+ uint32_t base_mac_ls4b; /* least significant 4 bytes */
+ nxge_mmac_t *mac_poolp;
+ npi_mac_addr_t mac_addr;
+
+ func_num = nxgep->function_num;
+ base_mmac_addr = (uint16_t *)&nxgep->factaddr;
+ mac_poolp = (nxge_mmac_t *)&nxgep->nxge_mmac_info;
+
+ base_mac_ls4b = ((uint32_t)base_mmac_addr[1]) << 16 | base_mmac_addr[2];
+
+ if (nxgep->niu_type == N2_NIU)
+ first_alt_mac_ls4b = base_mac_ls4b + 1;
+ else /* Neptune */
+ first_alt_mac_ls4b = base_mac_ls4b + (nxgep->nports - func_num)
+ + (func_num * (nxgep->nxge_mmac_info.num_mmac - 1));
+
+ for (i = 0; i < nxgep->nxge_mmac_info.num_mmac - 1; ++i) {
+ /*
+ * Populate shadow mac pool w/ available mac. so we dont
+ * have to read the h/w to search for a mac addr.
+ */
+ mmac_addr = (uint16_t *)&mac_poolp->mmac_pool[i];
+ mmac_addr[0] = base_mmac_addr[0];
+ mac_addr.w0 = mmac_addr[0];
+
+ mmac_addr[1] = (first_alt_mac_ls4b >> 16) & 0x0FFFF;
+ mac_addr.w1 = mmac_addr[1];
+
+ mmac_addr[2] = first_alt_mac_ls4b & 0x0FFFF;
+ mac_addr.w2 = mmac_addr[2];
+
+ /*
+ * Program the h/w alt. mac address, starting
+ * from reg1(reg0 corr. to unique mac addr)
+ */
+ (void) npi_mac_altaddr_entry(nxgep->npi_handle, OP_SET,
+ NXGE_GET_PORT_NUM(func_num), i, &mac_addr);
+ first_alt_mac_ls4b++;
+ }
+}
diff --git a/usr/src/uts/sun4v/io/nxge/nxge_zcp.c b/usr/src/uts/sun4v/io/nxge/nxge_zcp.c
new file mode 100644
index 0000000000..cc6288da93
--- /dev/null
+++ b/usr/src/uts/sun4v/io/nxge/nxge_zcp.c
@@ -0,0 +1,458 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <nxge_impl.h>
+#include <nxge_zcp.h>
+
+nxge_status_t
+nxge_zcp_init(p_nxge_t nxgep)
+{
+ uint8_t portn;
+ npi_handle_t handle;
+ zcp_iconfig_t istatus;
+ npi_status_t rs = NPI_SUCCESS;
+ int i;
+ zcp_ram_unit_t w_data;
+ zcp_ram_unit_t r_data;
+ uint32_t cfifo_depth;
+
+ handle = nxgep->npi_handle;
+ portn = NXGE_GET_PORT_NUM(nxgep->function_num);
+
+ if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) {
+ if (portn < 2)
+ cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
+ else
+ cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
+ } else if (nxgep->niu_type == N2_NIU)
+ cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
+
+ /* Clean up CFIFO */
+
+ w_data.w0 = 0;
+ w_data.w1 = 0;
+ w_data.w2 = 0;
+ w_data.w3 = 0;
+ w_data.w4 = 0;
+ for (i = 0; i < cfifo_depth; i++) {
+ if (npi_zcp_tt_cfifo_entry(handle, OP_SET, portn, i, &w_data)
+ != NPI_SUCCESS)
+ goto fail;
+ if (npi_zcp_tt_cfifo_entry(handle, OP_GET, portn, i, &r_data)
+ != NPI_SUCCESS)
+ goto fail;
+ }
+
+ if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS)
+ goto fail;
+ /*
+ * Making sure that error source is cleared if this is an
+ * injected error.
+ */
+ switch (portn) {
+ case 0:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
+ break;
+ case 1:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
+ break;
+ case 2:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
+ break;
+ case 3:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
+ break;
+ }
+
+ if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+ if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn));
+
+ return (NXGE_OK);
+
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_init: Fail to initialize ZCP Port #%d\n",
+ portn));
+ return (NXGE_ERROR | rs);
+}
+
+nxge_status_t
+nxge_zcp_handle_sys_errors(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ p_nxge_zcp_stats_t statsp;
+ uint8_t portn;
+ zcp_iconfig_t istatus;
+ boolean_t rxport_fatal = B_FALSE;
+ nxge_status_t status = NXGE_OK;
+
+ handle = nxgep->npi_handle;
+ statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
+ portn = nxgep->mac.portnum;
+
+ if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
+ return (NXGE_ERROR | rs);
+
+
+ if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) {
+ statsp->rrfifo_underrun++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: rrfifo_underrun"));
+ }
+ if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) {
+ statsp->rrfifo_overrun++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: buf_rrfifo_overrun"));
+ }
+ if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) {
+ statsp->rspfifo_uncorr_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: rspfifo_uncorr_err"));
+ }
+ if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) {
+ statsp->buffer_overflow++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: buffer_overflow"));
+ rxport_fatal = B_TRUE;
+ }
+ if (istatus & ICFG_ZCP_STAT_TBL_PERR) {
+ statsp->stat_tbl_perr++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: stat_tbl_perr"));
+ }
+ if (istatus & ICFG_ZCP_DYN_TBL_PERR) {
+ statsp->dyn_tbl_perr++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: dyn_tbl_perr"));
+ }
+ if (istatus & ICFG_ZCP_BUF_TBL_PERR) {
+ statsp->buf_tbl_perr++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: buf_tbl_perr"));
+ }
+ if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) {
+ statsp->tt_program_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: tt_program_err"));
+ }
+ if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) {
+ statsp->rsp_tt_index_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: rsp_tt_index_err"));
+ }
+ if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) {
+ statsp->slv_tt_index_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: slv_tt_index_err"));
+ }
+ if (istatus & ICFG_ZCP_TT_INDEX_ERR) {
+ statsp->zcp_tt_index_err++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: tt_index_err"));
+ }
+ if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
+ ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
+ ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
+ ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
+ statsp->cfifo_ecc++;
+ NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
+ NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "nxge_zcp_err_evnts: port%d buf_cfifo_ecc", portn));
+ rxport_fatal = B_TRUE;
+ }
+
+ /*
+ * Making sure that error source is cleared if this is an
+ * injected error.
+ */
+ switch (portn) {
+ case 0:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
+ break;
+ case 1:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
+ break;
+ case 2:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
+ break;
+ case 3:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
+ break;
+ }
+
+ (void) npi_zcp_clear_istatus(handle);
+
+ if (rxport_fatal) {
+ NXGE_DEBUG_MSG((nxgep, IPP_CTL,
+ " nxge_zcp_handle_sys_errors:"
+ " fatal Error on Port #%d\n",
+ portn));
+ status = nxge_zcp_fatal_err_recover(nxgep);
+#ifdef NXGE_FM
+ if (status == NXGE_OK) {
+ FM_SERVICE_RESTORED(nxgep);
+ }
+#endif
+ }
+ return (status);
+}
+
+void
+nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id)
+{
+ zcp_int_stat_reg_t zcps;
+ uint8_t portn = nxgep->mac.portnum;
+ zcp_ecc_ctrl_t ecc_ctrl;
+
+ switch (err_id) {
+ case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
+ ecc_ctrl.value = 0;
+ ecc_ctrl.bits.w0.cor_dbl = 1;
+ ecc_ctrl.bits.w0.cor_lst = 1;
+ ecc_ctrl.bits.w0.cor_all = 0;
+ switch (portn) {
+ case 0:
+ cmn_err(CE_NOTE,
+ "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
+ (unsigned long long)ecc_ctrl.value, portn);
+ NXGE_REG_WR64(nxgep->npi_handle,
+ ZCP_CFIFO_ECC_PORT0_REG,
+ ecc_ctrl.value);
+ break;
+ case 1:
+ cmn_err(CE_NOTE,
+ "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
+ (unsigned long long)ecc_ctrl.value, portn);
+ NXGE_REG_WR64(nxgep->npi_handle,
+ ZCP_CFIFO_ECC_PORT1_REG,
+ ecc_ctrl.value);
+ break;
+ case 2:
+ cmn_err(CE_NOTE,
+ "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
+ (unsigned long long)ecc_ctrl.value, portn);
+ NXGE_REG_WR64(nxgep->npi_handle,
+ ZCP_CFIFO_ECC_PORT2_REG,
+ ecc_ctrl.value);
+ break;
+ case 3:
+ cmn_err(CE_NOTE,
+ "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
+ (unsigned long long)ecc_ctrl.value, portn);
+ NXGE_REG_WR64(nxgep->npi_handle,
+ ZCP_CFIFO_ECC_PORT3_REG,
+ ecc_ctrl.value);
+ break;
+ }
+ break;
+ case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
+ case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
+ case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
+ case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
+ case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
+ case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
+ case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
+ case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
+ case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
+ NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
+ &zcps.value);
+ if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN)
+ zcps.bits.ldw.rrfifo_urun = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR)
+ zcps.bits.ldw.rspfifo_uc_err = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR)
+ zcps.bits.ldw.stat_tbl_perr = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR)
+ zcps.bits.ldw.dyn_tbl_perr = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR)
+ zcps.bits.ldw.buf_tbl_perr = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) {
+ switch (portn) {
+ case 0:
+ zcps.bits.ldw.cfifo_ecc0 = 1;
+ break;
+ case 1:
+ zcps.bits.ldw.cfifo_ecc1 = 1;
+ break;
+ case 2:
+ zcps.bits.ldw.cfifo_ecc2 = 1;
+ break;
+ case 3:
+ zcps.bits.ldw.cfifo_ecc3 = 1;
+ break;
+ }
+ default:
+ ;
+ }
+ if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN)
+ zcps.bits.ldw.rrfifo_orun = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW)
+ zcps.bits.ldw.buf_overflow = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR)
+ zcps.bits.ldw.tt_tbl_perr = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR)
+ zcps.bits.ldw.rsp_tt_index_err = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR)
+ zcps.bits.ldw.slv_tt_index_err = 1;
+ if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR)
+ zcps.bits.ldw.zcp_tt_index_err = 1;
+ cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
+ zcps.value);
+ NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
+ zcps.value);
+ break;
+ }
+}
+
+nxge_status_t
+nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
+{
+ npi_handle_t handle;
+ npi_status_t rs = NPI_SUCCESS;
+ nxge_status_t status = NXGE_OK;
+ uint8_t portn;
+ zcp_ram_unit_t w_data;
+ zcp_ram_unit_t r_data;
+ uint32_t cfifo_depth;
+ int i;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovering from RxPort error..."));
+
+ handle = nxgep->npi_handle;
+ portn = nxgep->mac.portnum;
+
+ /* Disable RxMAC */
+ if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
+ goto fail;
+
+ /* Make sure source is clear if this is an injected error */
+ switch (portn) {
+ case 0:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
+ break;
+ case 1:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
+ break;
+ case 2:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
+ break;
+ case 3:
+ NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
+ break;
+ }
+
+ /* Clear up CFIFO */
+
+ if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) {
+ if (portn < 2)
+ cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
+ else
+ cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
+ } else if (nxgep->niu_type == N2_NIU)
+ cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
+ w_data.w0 = 0;
+ w_data.w1 = 0;
+ w_data.w2 = 0;
+ w_data.w3 = 0;
+ w_data.w4 = 0;
+ for (i = 0; i < cfifo_depth; i++) {
+ if (npi_zcp_tt_cfifo_entry(handle, OP_SET, portn, i, &w_data)
+ != NPI_SUCCESS)
+ goto fail;
+ if (npi_zcp_tt_cfifo_entry(handle, OP_GET, portn, i, &r_data)
+ != NPI_SUCCESS)
+ goto fail;
+ }
+
+ /* When recovering from ZCP, RxDMA channel resets are not necessary */
+ /* Reset ZCP CFIFO */
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
+ if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ /* Reset IPP */
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
+ if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
+ if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
+
+ if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
+ goto fail;
+
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
+
+ if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
+ goto fail;
+
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+ "Recovery Sucessful, RxPort Restored"));
+ NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
+
+ return (NXGE_OK);
+fail:
+ NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
+ return (status | rs);
+}
diff --git a/usr/src/uts/sun4v/io/px/px_lib4v.c b/usr/src/uts/sun4v/io/px/px_lib4v.c
index ebbc341c9b..7e34da5fe2 100644
--- a/usr/src/uts/sun4v/io/px/px_lib4v.c
+++ b/usr/src/uts/sun4v/io/px/px_lib4v.c
@@ -323,9 +323,9 @@ px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages,
pfns[i] = MMU_PTOB(PX_ADDR2PFN(addr, pfn_index, flags, i));
/*
- * If HV VPCI version is 1.1 and higher, pass the BDF, phantom
- * function, and relax ordering information. Otherwise, justp pass
- * read or write attribute information.
+ * If HV VPCI version is 1.1 and higher, pass BDF, phantom function,
+ * and relaxed ordering attributes. Otherwise, pass only read or write
+ * attribute.
*/
if (px_vpci_min_ver == PX_VPCI_MINOR_VER_0)
attr = attr & (PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE);
@@ -1462,39 +1462,6 @@ int px_peekfault_cnt = 0;
int px_pokefault_cnt = 0;
#endif /* DEBUG */
-static int
-px_lib_bdf_from_dip(dev_info_t *rdip, uint32_t *bdf)
-{
- /* Start with an array of 8 reg spaces for now to cover most devices. */
- pci_regspec_t regspec_array[8];
- pci_regspec_t *regspec = regspec_array;
- int buflen = sizeof (regspec_array);
- boolean_t kmalloced = B_FALSE;
- int status;
-
- status = ddi_getlongprop_buf(DDI_DEV_T_ANY, rdip,
- DDI_PROP_DONTPASS, "reg", (caddr_t)regspec, &buflen);
-
- /* If need more space, fallback to kmem_alloc. */
- if (status == DDI_PROP_BUF_TOO_SMALL) {
- regspec = kmem_alloc(buflen, KM_SLEEP);
-
- status = ddi_getlongprop_buf(DDI_DEV_T_ANY, rdip,
- DDI_PROP_DONTPASS, "reg", (caddr_t)regspec, &buflen);
-
- kmalloced = B_TRUE;
- }
-
- /* Get phys_hi from first element. All have same bdf. */
- if (status == DDI_PROP_SUCCESS)
- *bdf = regspec->pci_phys_hi & (PCI_REG_BDFR_M ^ PCI_REG_REG_M);
-
- if (kmalloced)
- kmem_free(regspec, buflen);
-
- return ((status == DDI_PROP_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
-}
-
/*
* Do a safe write to a device.
*
@@ -1522,7 +1489,6 @@ px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
int err = DDI_SUCCESS;
uint64_t hvio_poke_status;
- uint32_t bdf;
uint32_t wrt_stat;
r_addr_t ra;
@@ -1536,13 +1502,6 @@ px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
*/
on_trap_data_t otd;
- if (px_lib_bdf_from_dip(rdip, &bdf) != DDI_SUCCESS) {
- DBG(DBG_LIB_DMA, px_p->px_dip,
- "poke: px_lib_bdf_from_dip failed\n");
- err = DDI_FAILURE;
- goto done;
- }
-
ra = (r_addr_t)va_to_pa((void *)dev_addr);
for (; repcount; repcount--) {
@@ -1581,7 +1540,7 @@ px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
pec_p->pec_ontrap_data = &otd;
hvio_poke_status = hvio_poke(px_p->px_dev_hdl, ra, size,
- pokeval, bdf, &wrt_stat);
+ pokeval, PCI_GET_BDF(rdip) << 8, &wrt_stat);
if (otd.ot_trap & OT_DATA_ACCESS)
err = DDI_FAILURE;
diff --git a/usr/src/uts/sun4v/io/px/px_lib4v.h b/usr/src/uts/sun4v/io/px/px_lib4v.h
index bccd4ec987..5dfb4a7e94 100644
--- a/usr/src/uts/sun4v/io/px/px_lib4v.h
+++ b/usr/src/uts/sun4v/io/px/px_lib4v.h
@@ -92,13 +92,14 @@ extern "C" {
/*
* VPCI API versioning.
*
- * Currently PX nexus driver supports VPCI API version 1.0
+ * Currently PX nexus driver supports VPCI API version 1.1
*/
#define PX_VPCI_MAJOR_VER_1 0x1ull
#define PX_VPCI_MAJOR_VER PX_VPCI_MAJOR_VER_1
#define PX_VPCI_MINOR_VER_0 0x0ull
-#define PX_VPCI_MINOR_VER PX_VPCI_MINOR_VER_0
+#define PX_VPCI_MINOR_VER_1 0x1ull
+#define PX_VPCI_MINOR_VER PX_VPCI_MINOR_VER_1
extern uint64_t hvio_config_get(devhandle_t dev_hdl, pci_device_t bdf,
pci_config_offset_t off, pci_config_size_t size, pci_cfg_data_t *data_p);
diff --git a/usr/src/uts/sun4v/io/vnex.c b/usr/src/uts/sun4v/io/vnex.c
index 25f0d3af94..a4caa49791 100644
--- a/usr/src/uts/sun4v/io/vnex.c
+++ b/usr/src/uts/sun4v/io/vnex.c
@@ -96,7 +96,8 @@ static struct vnex_pil_map vnex_name_to_pil[] = {
{"sunmc", PIL_3},
{"sunvts", PIL_3},
{"explorer", PIL_3},
- {"ncp", PIL_8}
+ {"ncp", PIL_8},
+ {"crypto", PIL_8}
};
#define VNEX_MAX_DEVS (sizeof (vnex_name_to_pil) / \
diff --git a/usr/src/uts/sun4v/ml/trap_table.s b/usr/src/uts/sun4v/ml/trap_table.s
index 54eaa49462..6b445e63d0 100644
--- a/usr/src/uts/sun4v/ml/trap_table.s
+++ b/usr/src/uts/sun4v/ml/trap_table.s
@@ -938,6 +938,8 @@ table_name/**/_dtlbmiss: ;\
MMU_FAULT_STATUS_AREA(%g7) ;\
ldx [%g7 + MMFSA_D_ADDR], %g2 /* address */ ;\
ldx [%g7 + MMFSA_D_CTX], %g3 /* g3 = ctx */ ;\
+ srlx %g2, MMU_PAGESHIFT, %g2 /* align address */ ;\
+ sllx %g2, MMU_PAGESHIFT, %g2 ;\
or %g2, %g3, %g2 /* TAG_ACCESS */ ;\
cmp %g3, INVALID_CONTEXT ;\
ble,pn %xcc, sfmmu_kdtlb_miss ;\
@@ -985,6 +987,8 @@ table_name/**/_itlbmiss: ;\
MMU_FAULT_STATUS_AREA(%g7) ;\
ldx [%g7 + MMFSA_I_ADDR], %g2 /* g2 = address */ ;\
ldx [%g7 + MMFSA_I_CTX], %g3 /* g3 = ctx */ ;\
+ srlx %g2, MMU_PAGESHIFT, %g2 /* align address */ ;\
+ sllx %g2, MMU_PAGESHIFT, %g2 ;\
or %g2, %g3, %g2 /* TAG_ACCESS */ ;\
cmp %g3, INVALID_CONTEXT ;\
ble,pn %xcc, sfmmu_kitlb_miss ;\
@@ -1017,6 +1021,8 @@ table_name/**/_itlbmiss: ;\
MMU_FAULT_STATUS_AREA(%g7) ;\
ldx [%g7 + MMFSA_D_ADDR], %g2 /* address */ ;\
ldx [%g7 + MMFSA_D_CTX], %g3 /* %g3 = ctx */ ;\
+ srlx %g2, MMU_PAGESHIFT, %g2 /* align address */ ;\
+ sllx %g2, MMU_PAGESHIFT, %g2 ;\
or %g2, %g3, %g2 /* TAG_ACCESS */ ;\
/* ;\
* g2 = tag access register ;\
diff --git a/usr/src/uts/sun4v/niagara2/Makefile b/usr/src/uts/sun4v/niagara2/Makefile
new file mode 100644
index 0000000000..f2b343e8ad
--- /dev/null
+++ b/usr/src/uts/sun4v/niagara2/Makefile
@@ -0,0 +1,108 @@
+#
+# 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
+#
+#
+# uts/sun4v/niagara2/Makefile
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This makefile drives the production of the UltraSPARC-T2 cpu module.
+#
+# sun4v implementation architecture dependent
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = SUNW,UltraSPARC-T2
+OBJECTS = $(NIAGARA2CPU_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(NIAGARA2CPU:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_PSM_CPU_DIR)/$(MODULE)
+
+CPU_DIR = .
+HERE = ../niagara2
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/sun4v/Makefile.sun4v
+
+#
+# Override defaults
+#
+CLEANFILES += $(CPULIB) $(SYM_MOD)
+
+#
+# Define targets
+#
+ALL_TARGET = $(SYM_MOD)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = def $(BINARY) $(ROOTMODULE)
+
+#
+# lint pass one enforcement
+#
+CFLAGS += $(CCVERBOSE) -DNIAGARA2_IMPL
+
+#
+# cpu-module-specific flags
+#
+CPPFLAGS += -DCPU_MODULE -DNIAGARA2_IMPL
+AS_CPPFLAGS += -DCPU_MODULE -DNIAGARA2_IMPL
+
+#
+# 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)
+
+$(CPULIB): $(BINARY)
+ $(BUILD.SO) $(BINARY)
+
+$(SYM_MOD): $(UNIX_O) $(CPULIB)
+ @echo "resolving symbols against unix.o"
+ @(cd $(UNIX_DIR); pwd; \
+ CPU_DIR=$(HERE) SYM_MOD=$(HERE)/$(SYM_MOD) $(MAKE) symcheck)
+
+# Include common targets.
+#
+include $(UTSBASE)/$(PLATFORM)/Makefile.targ
diff --git a/usr/src/uts/sun4v/niagara2_pcbe/Makefile b/usr/src/uts/sun4v/niagara2_pcbe/Makefile
new file mode 100644
index 0000000000..e19047fc79
--- /dev/null
+++ b/usr/src/uts/sun4v/niagara2_pcbe/Makefile
@@ -0,0 +1,77 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This Makefile builds the UltraSPARC-T2 Performance Counter BackEnd (PCBE).
+#
+
+UTSBASE = ../..
+
+#
+# Define module and object file sets.
+#
+MODULE = pcbe.SUNW,UltraSPARC-T2
+OBJECTS = $(N2_PCBE_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(N2_PCBE_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_PSM_PCBE_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/sun4v/Makefile.sun4v
+
+#
+# Define targets.
+#
+ALL_TARGET = $(BINARY)
+LINT_MODULE = niagara2_pcbe
+LINT_TARGET = $(LINT_MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# 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)/sun4v/Makefile.targ
diff --git a/usr/src/uts/sun4v/niumx/Makefile b/usr/src/uts/sun4v/niumx/Makefile
new file mode 100644
index 0000000000..b52a7da69a
--- /dev/null
+++ b/usr/src/uts/sun4v/niumx/Makefile
@@ -0,0 +1,104 @@
+#
+# 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
+#
+#
+# uts/sun4v/niumx/Makefile
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+# This makefile drives the production of the niumx driver kernel module
+#
+# sun4v implementation architecture dependent
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = niumx
+OBJECTS = $(NIUMX_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(NIUMX_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/sun4v/Makefile.sun4v
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Include SUN4 and SUN4U specific headers files
+#
+INC_PATH += -I$(UTSBASE)/sun4/io/niumx
+INC_PATH += -I$(UTSBASE)/sun4v/io/niumx
+
+#
+# lint pass one enforcement
+#
+CFLAGS += $(CCVERBOSE)
+
+#
+# Turn on doubleword alignment for 64 bit registers
+#
+CFLAGS += -dalign
+
+#
+# Dependency
+#
+LDFLAGS += -dy -Nmisc/busra -Nmisc/pcie
+
+#
+# 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)/sun4v/Makefile.targ
diff --git a/usr/src/uts/sun4v/nxge/Makefile b/usr/src/uts/sun4v/nxge/Makefile
new file mode 100644
index 0000000000..e04ad95393
--- /dev/null
+++ b/usr/src/uts/sun4v/nxge/Makefile
@@ -0,0 +1,140 @@
+#
+# 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
+#
+# uts/sun4v/nxge/Makefile
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This makefile drives the production of the N2 NIU
+# 10G Ethernet leaf driver kernel module.
+#
+# sun4v implementation architecture dependent
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = nxge
+OBJECTS = $(NXGE_OBJS:%=$(OBJS_DIR)/%) $(NXGE_NPI_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(NXGE_OBJS:%.o=$(LINTS_DIR)/%.ln) \
+ $(NXGE_NPI_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/sun4v/Makefile.sun4v
+
+#
+# Override defaults to build a unique, local modstubs.o.
+#
+MODSTUBS_DIR = $(OBJS_DIR)
+
+CLEANFILES += $(MODSTUBS_O)
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+#
+# Turn on doubleword alignment for 64 bit registers
+#
+CFLAGS += -dalign
+#
+# Include nxge specific header files
+#
+INC_PATH += -I$(UTSBASE)/sun4v/io/nxge/npi
+INC_PATH += -I$(UTSBASE)/sun4v/sys/nxge
+#
+#
+# lint pass one enforcement
+#
+CFLAGS += -DSOLARIS
+# NEMO
+#CFLAGS += -DNEMO
+#
+# Enable the following flags to run mac internal loopback under legion
+#CFLAGS += -DLEGION -DAXIS -DAXIS_DEBUG -DAXIS_DEBUG_LB -DSAM_DEBUG
+#
+# Enable the following flags to run mac internal loopback under AXIS
+# (NOTE: LEGION flag can be enabled too)
+#CFLAGS += -DAXIS_DEBUG -DAXIS -DAXIS_DEBUG_LB -DSAM_DEBUG -DLEGION
+#
+# Enable NXGE debug
+#CFLAGS += -DNXGE_DEBUG
+# Enable NPI debug
+#CFLAGS += -DNPI_DEBUG
+#CFLAGS += -DUSE_RX_BUFF_ATTR
+
+#CFLAGS += -DNIU_PA_WORKAROUND
+#CFLAGS += -DNIU_HV_WORKAROUND
+CFLAGS += -DNIU_LP_WORKAROUND
+
+LINTFLAGS += -DSOLARIS
+LINTFLAGS += -DNIU_LP_WORKAROUND
+#
+# STREAMS, DDI API limitations and other ON header file definitions such as ethernet.h
+# force us to turn off these lint checks.
+#
+LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
+LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW
+#
+# Driver depends on mac & IP
+#
+LDFLAGS += -dy -N misc/mac -N drv/ip
+
+#
+# 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)/$(PLATFORM)/Makefile.targ
diff --git a/usr/src/uts/sun4v/ontario/Makefile b/usr/src/uts/sun4v/ontario/Makefile
index 196cd5ce08..e0d6adac51 100644
--- a/usr/src/uts/sun4v/ontario/Makefile
+++ b/usr/src/uts/sun4v/ontario/Makefile
@@ -70,6 +70,8 @@ IMPLEMENTED_PLATFORM = SUNW,Sun-Fire-T200
LINKED_PLATFORMS = SUNW,Sun-Fire-T1000
LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T1000
LINKED_PLATFORMS += SUNW,Netra-T2000
+LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T5120
+LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T5220
LINKED_PLATFORMS += SUNW,SPARC-Enterprise-T2000
PPLINKED_PLATFORMS = SUNW,Netra-T2000
PPLINKED_PLATFORMS += SUNW,SPARC-Enterprise-T2000
diff --git a/usr/src/uts/sun4v/os/error.c b/usr/src/uts/sun4v/os/error.c
index 8be2bf26c2..965ddce7c0 100644
--- a/usr/src/uts/sun4v/os/error.c
+++ b/usr/src/uts/sun4v/os/error.c
@@ -39,6 +39,7 @@
#include <sys/error.h>
#include <sys/fm/util.h>
#include <sys/ivintr.h>
+#include <sys/archsystm.h>
#define MAX_CE_FLTS 10
#define MAX_ASYNC_FLTS 6
@@ -91,6 +92,8 @@ static int errh_error_protected(struct regs *, struct async_flt *, int *);
static void errh_rq_full(struct async_flt *);
static void ue_drain(void *, struct async_flt *, errorq_elem_t *);
static void ce_drain(void *, struct async_flt *, errorq_elem_t *);
+static void errh_handle_attr(errh_async_flt_t *);
+static void errh_handle_asr(errh_async_flt_t *);
/*ARGSUSED*/
void
@@ -123,6 +126,11 @@ process_resumable_error(struct regs *rp, uint32_t head_offset,
switch (errh_flt.errh_er.desc) {
case ERRH_DESC_UCOR_RE:
+ /*
+ * Check error attribute, handle individual error
+ * if it is needed.
+ */
+ errh_handle_attr(&errh_flt);
break;
case ERRH_DESC_WARN_RE:
@@ -284,6 +292,12 @@ process_nonresumable_error(struct regs *rp, uint64_t flags,
}
/*
+ * Check error attribute, handle individual error
+ * if it is needed.
+ */
+ errh_handle_attr(&errh_flt);
+
+ /*
* If PIO error, we need to query the bus nexus
* for fatal errors.
*/
@@ -746,3 +760,60 @@ nrq_overflow(struct regs *rp)
{
fm_panic("Nonresumable queue full");
}
+
+/*
+ * This is the place for special error handling for individual errors.
+ */
+static void
+errh_handle_attr(errh_async_flt_t *errh_fltp)
+{
+ switch (errh_fltp->errh_er.attr & ~ERRH_MODE_MASK) {
+ case ERRH_ATTR_CPU:
+ case ERRH_ATTR_MEM:
+ case ERRH_ATTR_PIO:
+ case ERRH_ATTR_IRF:
+ case ERRH_ATTR_FRF:
+ case ERRH_ATTR_SHUT:
+ break;
+
+ case ERRH_ATTR_ASR:
+ errh_handle_asr(errh_fltp);
+ break;
+
+ case ERRH_ATTR_ASI:
+ case ERRH_ATTR_PREG:
+ case ERRH_ATTR_RQF:
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Handle ASR bit set in ATTR
+ */
+static void
+errh_handle_asr(errh_async_flt_t *errh_fltp)
+{
+ uint64_t current_tick;
+
+ switch (errh_fltp->errh_er.reg) {
+ case ASR_REG_VALID | ASR_REG_TICK:
+ /*
+ * For Tick Compare Register error, it only happens when
+ * the register is being read or compared with the %tick
+ * register. Since we lost the contents of the register,
+ * we set the %tick_compr in the future. An interrupt will
+ * happen when %tick matches the value field of %tick_compr.
+ */
+ current_tick = (uint64_t)gettick();
+ tickcmpr_set(current_tick);
+ /* Do not panic */
+ errh_fltp->cmn_asyncflt.flt_panic = 0;
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/usr/src/uts/sun4v/os/mach_startup.c b/usr/src/uts/sun4v/os/mach_startup.c
index 7024e54ac5..6a7175c4eb 100644
--- a/usr/src/uts/sun4v/os/mach_startup.c
+++ b/usr/src/uts/sun4v/os/mach_startup.c
@@ -77,6 +77,14 @@ phys_install_has_changed(void)
}
+#ifdef N2_IDLE_WORKAROUND
+/*
+ * Tuneable to control enabling of IDLE loop workaround on Niagara2 1.x parts.
+ * This workaround will be removed before the RR.
+ */
+int n2_idle_workaround;
+#endif
+
/*
* Halt the present CPU until awoken via an interrupt
*/
@@ -87,6 +95,7 @@ cpu_halt(void)
processorid_t cpun = cpup->cpu_id;
cpupart_t *cp = cpup->cpu_part;
int hset_update = 1;
+ volatile int *p = &cpup->cpu_disp->disp_nrunnable;
uint_t s;
/*
@@ -129,8 +138,24 @@ cpu_halt(void)
return;
}
+#ifdef N2_IDLE_WORKAROUND
/*
- * We're on our way to being halted.
+ * The following workaround for Niagara2, when enabled, forces the
+ * IDLE CPU to wait in a tight loop until something becomes runnable
+ * locally, minimizing the overall CPU usage on an IDLE CPU.
+ */
+ if (n2_idle_workaround) {
+ while (cpup->cpu_disp->disp_nrunnable == 0) {
+ (void) hv_cpu_yield();
+ }
+ }
+#endif
+
+ /*
+ * We're on our way to being halted. Wait until something becomes
+ * runnable locally or we are awaken (i.e. removed from the halt set).
+ * Note that the call to hv_cpu_yield() can return even if we have
+ * nothing to do.
*
* Disable interrupts now, so that we'll awaken immediately
* after halting if someone tries to poke us between now and
@@ -144,36 +169,22 @@ cpu_halt(void)
* is important.
* cpu_wakeup() must clear, then poke.
* cpu_halt() must disable interrupts, then check for the bit.
- */
- s = disable_vec_intr();
-
- if (hset_update && !CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) {
- cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
- enable_vec_intr(s);
- return;
- }
-
- /*
+ *
* The check for anything locally runnable is here for performance
* and isn't needed for correctness. disp_nrunnable ought to be
* in our cache still, so it's inexpensive to check, and if there
* is anything runnable we won't have to wait for the poke.
+ *
*/
- if (cpup->cpu_disp->disp_nrunnable != 0) {
- if (hset_update) {
- cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
- CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
- }
+ s = disable_vec_intr();
+ while (*p == 0 &&
+ (!hset_update || CPU_IN_SET(cp->cp_mach->mc_haltset, cpun))) {
+ (void) hv_cpu_yield();
enable_vec_intr(s);
- return;
+ s = disable_vec_intr();
}
/*
- * Halt the strand
- */
- (void) hv_cpu_yield();
-
- /*
* We're no longer halted
*/
enable_vec_intr(s);
diff --git a/usr/src/uts/sun4v/pcbe/niagara2_pcbe.c b/usr/src/uts/sun4v/pcbe/niagara2_pcbe.c
new file mode 100644
index 0000000000..1e34194fa0
--- /dev/null
+++ b/usr/src/uts/sun4v/pcbe/niagara2_pcbe.c
@@ -0,0 +1,582 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Niagara2 Performance Counter Backend
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/cpuvar.h>
+#include <sys/systm.h>
+#include <sys/archsystm.h>
+#include <sys/cmn_err.h>
+#include <sys/cpc_impl.h>
+#include <sys/cpc_pcbe.h>
+#include <sys/modctl.h>
+#include <sys/machsystm.h>
+#include <sys/sdt.h>
+#include <sys/niagara2regs.h>
+#include <sys/hsvc.h>
+
+static int ni2_pcbe_init(void);
+static uint_t ni2_pcbe_ncounters(void);
+static const char *ni2_pcbe_impl_name(void);
+static const char *ni2_pcbe_cpuref(void);
+static char *ni2_pcbe_list_events(uint_t picnum);
+static char *ni2_pcbe_list_attrs(void);
+static uint64_t ni2_pcbe_event_coverage(char *event);
+static uint64_t ni2_pcbe_overflow_bitmap(void);
+static int ni2_pcbe_configure(uint_t picnum, char *event, uint64_t preset,
+ uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
+ void *token);
+static void ni2_pcbe_program(void *token);
+static void ni2_pcbe_allstop(void);
+static void ni2_pcbe_sample(void *token);
+static void ni2_pcbe_free(void *config);
+
+extern void ultra_setpcr(uint64_t);
+extern uint64_t ultra_getpcr(void);
+extern void ultra_setpic(uint64_t);
+extern uint64_t ultra_getpic(void);
+extern uint64_t ultra_gettick(void);
+extern char cpu_module_name[];
+
+pcbe_ops_t ni2_pcbe_ops = {
+ PCBE_VER_1,
+ CPC_CAP_OVERFLOW_INTERRUPT | CPC_CAP_OVERFLOW_PRECISE,
+ ni2_pcbe_ncounters,
+ ni2_pcbe_impl_name,
+ ni2_pcbe_cpuref,
+ ni2_pcbe_list_events,
+ ni2_pcbe_list_attrs,
+ ni2_pcbe_event_coverage,
+ ni2_pcbe_overflow_bitmap,
+ ni2_pcbe_configure,
+ ni2_pcbe_program,
+ ni2_pcbe_allstop,
+ ni2_pcbe_sample,
+ ni2_pcbe_free
+};
+
+typedef struct _ni2_pcbe_config {
+ uint_t pcbe_picno; /* 0 for pic0 or 1 for pic1 */
+ uint32_t pcbe_evsel; /* %pcr event code unshifted */
+ uint32_t pcbe_flags; /* hpriv/user/system/priv */
+ uint32_t pcbe_pic; /* unshifted raw %pic value */
+} ni2_pcbe_config_t;
+
+typedef struct _ni2_event {
+ const char *name;
+ const uint32_t emask;
+ const uint32_t emask_valid; /* Mask of unreserved MASK bits */
+} ni2_event_t;
+
+#define ULTRA_PCR_PRIVPIC (UINT64_C(1) << CPC_NIAGARA2_PCR_PRIVPIC_SHIFT)
+#define EV_END {NULL, 0, 0}
+
+static const uint64_t allstopped = ULTRA_PCR_PRIVPIC;
+
+static ni2_event_t ni2_events[] = {
+ { "Idle_strands", 0x000, 0x00 },
+ { "Br_completed", 0x201, 0x7f },
+ { "Br_taken", 0x202, 0x7f },
+ { "Instr_FGU_arithmetic", 0x204, 0x7f },
+ { "Instr_ld", 0x208, 0x7f },
+ { "Instr_st", 0x210, 0x7f },
+ { "Instr_sw", 0x220, 0x7f },
+ { "Instr_other", 0x240, 0x7f },
+ { "Instr_cnt", 0x27d, 0x7f },
+ { "IC_miss", 0x301, 0x3f },
+ { "DC_miss", 0x302, 0x3f },
+ { "ITLB_miss", 0x304, 0x3f },
+ { "DTLB_miss", 0x308, 0x3f },
+ { "L2_imiss", 0x310, 0x3f },
+ { "L2_dmiss_ld", 0x320, 0x3f },
+ { "ITLB_HWTW_ref_L2", 0x404, 0x3c },
+ { "DTLB_HWTW_ref_L2", 0x408, 0x3c },
+ { "ITLB_HWTW_miss_L2", 0x410, 0x3c },
+ { "DTLB_HWTW_miss_L2", 0x420, 0x3c },
+ { "Stream_ld_to_PCX", 0x501, 0x3f },
+ { "Stream_st_to_PCX", 0x502, 0x3f },
+ { "CPU_ld_to_PCX", 0x504, 0x3f },
+ { "CPU_ifetch_to_PCX", 0x508, 0x3f },
+ { "CPU_st_to_PCX", 0x510, 0x3f },
+ { "MMU_ld_to_PCX", 0x520, 0x3f },
+ { "DES_3DES_op", 0x601, 0x3f },
+ { "AES_op", 0x602, 0x3f },
+ { "RC4_op", 0x604, 0x3f },
+ { "MD5_SHA-1_SHA-256_op", 0x608, 0x3f },
+ { "MA_op", 0x610, 0x3f },
+ { "CRC_TCPIP_cksum", 0x620, 0x3f },
+ { "DES_3DES_busy_cycle", 0x701, 0x3f },
+ { "AES_busy_cycle", 0x702, 0x3f },
+ { "RC4_busy_cycle", 0x704, 0x3f },
+ { "MD5_SHA-1_SHA-256_busy_cycle", 0x708, 0x3f },
+ { "MA_busy_cycle", 0x710, 0x3f },
+ { "CRC_MPA_cksum", 0x720, 0x3f },
+ EV_END
+};
+
+static const char *ni2_impl_name = "UltraSPARC T2";
+static char *evlist;
+static size_t evlist_sz;
+static uint16_t pcr_pic0_mask;
+static uint16_t pcr_pic1_mask;
+
+#define CPU_REF_URL " Documentation for Sun processors can be found at: " \
+ "http://www.sun.com/processors/manuals"
+
+static const char *niagara2_cpuref = "See the \"UltraSPARC T2 User's Manual\" "
+ "for descriptions of these events." CPU_REF_URL;
+
+static boolean_t niagara2_hsvc_available = B_TRUE;
+
+static int
+ni2_pcbe_init(void)
+{
+ ni2_event_t *evp;
+ int status;
+ uint64_t niagara2_hsvc_major;
+ uint64_t niagara2_hsvc_minor;
+
+ pcr_pic0_mask = CPC_NIAGARA2_PCR_PIC0_MASK;
+ pcr_pic1_mask = CPC_NIAGARA2_PCR_PIC1_MASK;
+
+ /*
+ * Validate API version for Niagara2 specific hypervisor services
+ */
+ status = hsvc_version(HSVC_GROUP_NIAGARA2_CPU, &niagara2_hsvc_major,
+ &niagara2_hsvc_minor);
+ if ((status != 0) || (niagara2_hsvc_major != NIAGARA2_HSVC_MAJOR)) {
+ cmn_err(CE_WARN, "hypervisor services not negotiated "
+ "or unsupported major number: group: 0x%x major: 0x%lx "
+ "minor: 0x%lx errno: %d", HSVC_GROUP_NIAGARA2_CPU,
+ niagara2_hsvc_major, niagara2_hsvc_minor, status);
+ niagara2_hsvc_available = B_FALSE;
+ }
+ /*
+ * Construct event list.
+ *
+ * First pass: Calculate size needed. We'll need an additional byte
+ * for the NULL pointer during the last strcat.
+ *
+ * Second pass: Copy strings.
+ */
+ for (evp = ni2_events; evp->name != NULL; evp++)
+ evlist_sz += strlen(evp->name) + 1;
+
+ evlist = kmem_alloc(evlist_sz + 1, KM_SLEEP);
+ evlist[0] = '\0';
+
+ for (evp = ni2_events; evp->name != NULL; evp++) {
+ (void) strcat(evlist, evp->name);
+ (void) strcat(evlist, ",");
+ }
+ /*
+ * Remove trailing comma.
+ */
+ evlist[evlist_sz - 1] = '\0';
+
+ return (0);
+}
+
+static uint_t
+ni2_pcbe_ncounters(void)
+{
+ return (2);
+}
+
+static const char *
+ni2_pcbe_impl_name(void)
+{
+ return (ni2_impl_name);
+}
+
+static const char *
+ni2_pcbe_cpuref(void)
+{
+ return (niagara2_cpuref);
+}
+
+static char *
+ni2_pcbe_list_events(uint_t picnum)
+{
+ ASSERT(picnum < cpc_ncounters);
+
+ return (evlist);
+}
+
+static char *
+ni2_pcbe_list_attrs(void)
+{
+ if (niagara2_hsvc_available == B_TRUE)
+ return ("hpriv,emask");
+ else
+ return ("emask");
+}
+
+static ni2_event_t *
+find_event(char *name)
+{
+ ni2_event_t *evp;
+
+ for (evp = ni2_events; evp->name != NULL; evp++)
+ if (strcmp(name, evp->name) == 0)
+ return (evp);
+
+ return (NULL);
+}
+
+/*ARGSUSED*/
+static uint64_t
+ni2_pcbe_event_coverage(char *event)
+{
+ /*
+ * Fortunately, both pic0 and pic1 can count all events.
+ */
+ return (0x3);
+}
+
+#ifdef N2_ERRATUM_112
+uint64_t ni2_ov_tstamp[NCPU]; /* last overflow time stamp */
+uint64_t ni2_ov_spurious_range = 1000000; /* 1 msec at 1GHz */
+#endif
+
+/*
+ * These processors cannot tell which counter overflowed. The PCBE interface
+ * requires such processors to act as if _all_ counters had overflowed.
+ */
+static uint64_t
+ni2_pcbe_overflow_bitmap(void)
+{
+ uint64_t pcr, overflow;
+ uint64_t pic;
+ uint32_t pic0, pic1;
+ boolean_t update_pic = B_FALSE;
+#ifdef N2_ERRATUM_112
+ uint64_t tstamp;
+ processorid_t cpun;
+#endif
+
+ ASSERT(getpil() >= DISP_LEVEL);
+ pcr = ultra_getpcr();
+ DTRACE_PROBE1(niagara2__getpcr, uint64_t, pcr);
+ overflow = (pcr & CPC_NIAGARA2_PCR_OV0_MASK) >>
+ CPC_NIAGARA2_PCR_OV0_SHIFT;
+ overflow |= (pcr & CPC_NIAGARA2_PCR_OV1_MASK) >>
+ CPC_NIAGARA2_PCR_OV1_SHIFT;
+#ifdef N2_ERRATUM_112
+ /*
+ * Niagara2 1.x silicon can generate a duplicate overflow trap per
+ * event. If we take an overflow trap with no counters overflowing,
+ * return a non-zero bitmask with no OV bit set for supported
+ * counter so that the framework can ignore this trap.
+ */
+ cpun = CPU->cpu_id;
+ tstamp = ultra_gettick();
+ if (overflow)
+ ni2_ov_tstamp[cpun] = tstamp;
+ else if (tstamp < (ni2_ov_tstamp[cpun] + ni2_ov_spurious_range))
+ overflow |= 1ULL << 63;
+#endif
+ pic = ultra_getpic();
+ pic0 = (uint32_t)(pic & PIC0_MASK);
+ pic1 = (uint32_t)((pic >> PIC1_SHIFT) & PIC0_MASK);
+
+#ifdef N2_ERRATUM_134
+ /*
+ * In Niagara2 1.x silicon, PMU doesn't set OV bit for precise events.
+ * So, if we take a trap with the counter within the overflow range
+ * and the OV bit is not set, we assume OV bit should have been set.
+ */
+
+ if (PIC_IN_OV_RANGE(pic0))
+ overflow |= 0x1;
+ if (PIC_IN_OV_RANGE(pic1))
+ overflow |= 0x2;
+#endif
+ /*
+ * Reset the pic, if it is within the overflow range.
+ */
+ if ((overflow & 0x1) && (PIC_IN_OV_RANGE(pic0))) {
+ pic0 = 0;
+ update_pic = B_TRUE;
+ }
+ if ((overflow & 0x2) && (PIC_IN_OV_RANGE(pic1))) {
+ pic1 = 0;
+ update_pic = B_TRUE;
+ }
+
+ if (update_pic)
+ ultra_setpic(((uint64_t)pic1 << PIC1_SHIFT) | pic0);
+
+ return (overflow);
+}
+
+/*ARGSUSED*/
+static int
+ni2_pcbe_configure(uint_t picnum, char *event, uint64_t preset, uint32_t flags,
+ uint_t nattrs, kcpc_attr_t *attrs, void **data, void *token)
+{
+ ni2_pcbe_config_t *cfg;
+ ni2_pcbe_config_t *other_config;
+ ni2_event_t *evp;
+ int i;
+ uint32_t evsel;
+
+ /*
+ * If we've been handed an existing configuration, we need only preset
+ * the counter value.
+ */
+ if (*data != NULL) {
+ cfg = *data;
+ cfg->pcbe_pic = (uint32_t)preset;
+ return (0);
+ }
+
+ if (picnum > 1)
+ return (CPC_INVALID_PICNUM);
+
+ if ((evp = find_event(event)) == NULL)
+ return (CPC_INVALID_EVENT);
+
+ evsel = evp->emask;
+
+ for (i = 0; i < nattrs; i++) {
+ if (strcmp(attrs[i].ka_name, "hpriv") == 0) {
+ if (attrs[i].ka_val != 0)
+ flags |= CPC_COUNT_HPRIV;
+ } else if (strcmp(attrs[i].ka_name, "emask") == 0) {
+ if ((attrs[i].ka_val | evp->emask_valid) !=
+ evp->emask_valid)
+ return (CPC_ATTRIBUTE_OUT_OF_RANGE);
+ evsel |= attrs[i].ka_val;
+ } else
+ return (CPC_INVALID_ATTRIBUTE);
+ }
+
+ /*
+ * Find other requests that will be programmed with this one, and ensure
+ * the flags don't conflict.
+ */
+ if (((other_config = kcpc_next_config(token, NULL, NULL)) != NULL) &&
+ (other_config->pcbe_flags != flags))
+ return (CPC_CONFLICTING_REQS);
+
+ cfg = kmem_alloc(sizeof (*cfg), KM_SLEEP);
+
+ cfg->pcbe_picno = picnum;
+ cfg->pcbe_evsel = evsel;
+ cfg->pcbe_flags = flags;
+ cfg->pcbe_pic = (uint32_t)preset;
+
+ *data = cfg;
+ return (0);
+}
+
+static void
+ni2_pcbe_program(void *token)
+{
+ ni2_pcbe_config_t *pic0;
+ ni2_pcbe_config_t *pic1;
+ ni2_pcbe_config_t *tmp;
+ ni2_pcbe_config_t nullcfg = { 1, 0, 0, 0 };
+ uint64_t pcr;
+ uint64_t curpic;
+ uint64_t toe;
+
+ /* enable trap-on-event for pic0 and pic1 */
+ toe = (CPC_COUNT_TOE0 | CPC_COUNT_TOE1);
+
+ if ((pic0 = (ni2_pcbe_config_t *)kcpc_next_config(token, NULL, NULL)) ==
+ NULL)
+ panic("ni2_pcbe: token %p has no configs", token);
+
+ if ((pic1 = kcpc_next_config(token, pic0, NULL)) == NULL) {
+ pic1 = &nullcfg;
+ nullcfg.pcbe_flags = pic0->pcbe_flags;
+ toe = CPC_COUNT_TOE0; /* enable trap-on-event for pic0 */
+ }
+
+ if (pic0->pcbe_picno != 0) {
+ /*
+ * pic0 is counter 1, so if we need the null config it should
+ * be counter 0.
+ */
+ nullcfg.pcbe_picno = 0;
+ tmp = pic0;
+ pic0 = pic1;
+ pic1 = tmp;
+ toe = CPC_COUNT_TOE1; /* enable trap-on-event for pic1 */
+ }
+
+ if (pic0->pcbe_picno != 0 || pic1->pcbe_picno != 1)
+ panic("%s: bad config on token %p\n", ni2_impl_name, token);
+
+ /*
+ * UltraSPARC does not allow pic0 to be configured differently
+ * from pic1. If the flags on these two configurations are
+ * different, they are incompatible. This condition should be
+ * caught at configure time.
+ */
+ ASSERT(pic0->pcbe_flags == pic1->pcbe_flags);
+
+ ultra_setpcr(allstopped);
+ ultra_setpic(((uint64_t)pic1->pcbe_pic << PIC1_SHIFT) |
+ (uint64_t)pic0->pcbe_pic);
+
+ pcr = (pic0->pcbe_evsel & pcr_pic0_mask) << CPC_NIAGARA2_PCR_PIC0_SHIFT;
+ pcr |= (pic1->pcbe_evsel & pcr_pic1_mask) <<
+ CPC_NIAGARA2_PCR_PIC1_SHIFT;
+
+ if (pic0->pcbe_flags & CPC_COUNT_USER)
+ pcr |= (1ull << CPC_NIAGARA2_PCR_USR_SHIFT);
+ if (pic0->pcbe_flags & CPC_COUNT_SYSTEM)
+ pcr |= (1ull << CPC_NIAGARA2_PCR_SYS_SHIFT);
+ if (pic0->pcbe_flags & CPC_COUNT_HPRIV)
+ pcr |= (1ull << CPC_NIAGARA2_PCR_HPRIV_SHIFT);
+ pcr |= toe;
+
+ DTRACE_PROBE1(niagara2__setpcr, uint64_t, pcr);
+
+ /*
+ * PCR is set by HV using API call hv_niagara_setperf().
+ * Silently ignore hvpriv events if access is denied.
+ */
+ if (pic0->pcbe_flags & CPC_COUNT_HPRIV) {
+ if (hv_niagara_setperf(HV_NIAGARA_SPARC_CTL, pcr) != 0)
+ ultra_setpcr(pcr);
+ } else
+ ultra_setpcr(pcr);
+
+ /*
+ * On UltraSPARC, only read-to-read counts are accurate. We cannot
+ * expect the value we wrote into the PIC, above, to be there after
+ * starting the counter. We must sample the counter value now and use
+ * that as the baseline for future samples.
+ */
+ curpic = ultra_getpic();
+ pic0->pcbe_pic = (uint32_t)(curpic & PIC0_MASK);
+ pic1->pcbe_pic = (uint32_t)(curpic >> PIC1_SHIFT);
+
+ DTRACE_PROBE1(niagara2__newpic, uint64_t, curpic);
+}
+
+static void
+ni2_pcbe_allstop(void)
+{
+ ultra_setpcr(allstopped);
+}
+
+static void
+ni2_pcbe_sample(void *token)
+{
+ uint64_t curpic;
+ int64_t diff;
+ uint64_t *pic0_data;
+ uint64_t *pic1_data;
+ uint64_t *dtmp;
+ uint64_t tmp;
+ ni2_pcbe_config_t *pic0;
+ ni2_pcbe_config_t *pic1;
+ ni2_pcbe_config_t nullcfg = { 1, 0, 0, 0 };
+ ni2_pcbe_config_t *ctmp;
+
+ curpic = ultra_getpic();
+ DTRACE_PROBE1(niagara2__getpic, uint64_t, curpic);
+
+ if ((pic0 = kcpc_next_config(token, NULL, &pic0_data)) == NULL)
+ panic("%s: token %p has no configs", ni2_impl_name, token);
+
+ if ((pic1 = kcpc_next_config(token, pic0, &pic1_data)) == NULL) {
+ pic1 = &nullcfg;
+ pic1_data = &tmp;
+ }
+
+ if (pic0->pcbe_picno != 0) {
+ nullcfg.pcbe_picno = 0;
+ ctmp = pic0;
+ pic0 = pic1;
+ pic1 = ctmp;
+ dtmp = pic0_data;
+ pic0_data = pic1_data;
+ pic1_data = dtmp;
+ }
+
+ if (pic0->pcbe_picno != 0 || pic1->pcbe_picno != 1)
+ panic("%s: bad config on token %p\n", ni2_impl_name, token);
+
+ diff = (curpic & PIC0_MASK) - (uint64_t)pic0->pcbe_pic;
+ if (diff < 0)
+ diff += (1ll << 32);
+ *pic0_data += diff;
+
+ diff = (curpic >> 32) - (uint64_t)pic1->pcbe_pic;
+ if (diff < 0)
+ diff += (1ll << 32);
+ *pic1_data += diff;
+
+ pic0->pcbe_pic = (uint32_t)(curpic & PIC0_MASK);
+ pic1->pcbe_pic = (uint32_t)(curpic >> PIC1_SHIFT);
+}
+
+static void
+ni2_pcbe_free(void *config)
+{
+ kmem_free(config, sizeof (ni2_pcbe_config_t));
+}
+
+
+static struct modlpcbe modlpcbe = {
+ &mod_pcbeops,
+ "UltraSPARC T2 Performance Counters v%I%",
+ &ni2_pcbe_ops
+};
+
+static struct modlinkage modl = {
+ MODREV_1,
+ &modlpcbe,
+};
+
+int
+_init(void)
+{
+ if (ni2_pcbe_init() != 0)
+ return (ENOTSUP);
+ return (mod_install(&modl));
+}
+
+int
+_fini(void)
+{
+ return (mod_remove(&modl));
+}
+
+int
+_info(struct modinfo *mi)
+{
+ return (mod_info(&modl, mi));
+}
diff --git a/usr/src/uts/sun4v/sys/Makefile b/usr/src/uts/sun4v/sys/Makefile
index f8f376cdc7..2e545e67a8 100644
--- a/usr/src/uts/sun4v/sys/Makefile
+++ b/usr/src/uts/sun4v/sys/Makefile
@@ -93,6 +93,30 @@ CLOSED_HDRS= \
memtestio_ni.h \
memtestio_v.h
+NXGEHDRS= \
+ nxge.h \
+ nxge_common.h \
+ nxge_common_impl.h \
+ nxge_defs.h \
+ nxge_hw.h \
+ nxge_impl.h \
+ nxge_ipp.h \
+ nxge_ipp_hw.h \
+ nxge_mac.h \
+ nxge_mac_hw.h \
+ nxge_fflp.h \
+ nxge_fflp_hw.h \
+ nxge_mii.h \
+ nxge_rxdma.h \
+ nxge_rxdma_hw.h \
+ nxge_str_cfg.h \
+ nxge_txc.h \
+ nxge_txc_hw.h \
+ nxge_txdma.h \
+ nxge_txdma_hw.h \
+ nxge_virtual.h \
+ nxge_espc.h
+
ROOTHDRS= $(HDRS:%=$(USR_PSM_ISYS_DIR)/%)
$(CLOSED_BUILD)ROOTHDRS += $(CLOSED_HDRS:%=$(USR_PSM_ISYS_DIR)/%)
@@ -106,7 +130,9 @@ ROOTLINK= $(ROOTDIR)/uts/$(PLATFORM)/sys
LINKDEST= ../../../../platform/$(PLATFORM)/include/sys
CHECKHDRS= $(HDRS:%.h=%.check) \
- $(SUN4_HDRS:%.h=%.cmncheck)
+ $(SUN4_HDRS:%.h=%.cmncheck) \
+ $(NXGEHDRS:%.h=nxge/%.check)
+
$(CLOSED_BUILD)CHECKHDRS += \
$(CLOSED_HDRS:%.h=%.check) \
$(CLOSED_SUN4_HDRS:%.h=%.cmncheck)
diff --git a/usr/src/uts/sun4v/sys/error.h b/usr/src/uts/sun4v/sys/error.h
index defd5c9508..0ceb5e6305 100644
--- a/usr/src/uts/sun4v/sys/error.h
+++ b/usr/src/uts/sun4v/sys/error.h
@@ -64,6 +64,10 @@ extern "C" {
#define ERRH_ATTR_IRF 0x00000008 /* Integer register file */
/* Floating-point register file */
#define ERRH_ATTR_FRF 0x00000010
+#define ERRH_ATTR_SHUT 0x00000020 /* Shutdown request */
+#define ERRH_ATTR_ASR 0x00000040 /* Sun4v ASR */
+#define ERRH_ATTR_ASI 0x00000080 /* Sun4v ASI */
+#define ERRH_ATTR_PREG 0x00000100 /* Sun4v Privileged Register */
#define ERRH_ATTR_RQF 0x80000000 /* Resumablee Queue Full */
/*
@@ -76,6 +80,12 @@ extern "C" {
#define ERRH_MODE_PRIV 2
/*
+ * ASR register number
+ */
+#define ASR_REG_VALID 0x8000 /* Valid bit for register field */
+#define ASR_REG_TICK 0x17 /* Tick Compare Register */
+
+/*
* For the second argument passed to process_nonresumable_error(), it is
* an uint64_t. The upper 32 bits are reserved for various flags, the
* lower 32 bits are used to pass the "current tl-1". Right now only bit
@@ -112,6 +122,10 @@ typedef struct {
uint64_t ra; /* Real address */
uint32_t sz; /* Size of affected mem region */
uint16_t cpuid; /* Virtual ID of the affected CPU */
+ uint16_t secs; /* Seconds */
+ uint8_t asi; /* ASI */
+ uint8_t rsvd; /* Padding for ASI */
+ uint16_t reg; /* Value of the ASR register number */
} errh_er_t;
typedef struct errh_async_flt {
diff --git a/usr/src/uts/sun4v/sys/hsvc.h b/usr/src/uts/sun4v/sys/hsvc.h
index 72e2042a80..4241b31166 100644
--- a/usr/src/uts/sun4v/sys/hsvc.h
+++ b/usr/src/uts/sun4v/sys/hsvc.h
@@ -48,8 +48,11 @@ extern "C" {
#define HSVC_GROUP_LDC 0x0101
#define HSVC_GROUP_VSC 0x0102
#define HSVC_GROUP_NCS 0x0103
+#define HSVC_GROUP_RNG 0x0104
#define HSVC_GROUP_NIAGARA_CPU 0x0200
#define HSVC_GROUP_FIRE_PERF 0x0201
+#define HSVC_GROUP_NIAGARA2_CPU 0x0202
+#define HSVC_GROUP_NIU 0x0204
#define HSVC_GROUP_DIAG 0x0300
#ifndef _ASM
diff --git a/usr/src/uts/sun4v/sys/n2cp.h b/usr/src/uts/sun4v/sys/n2cp.h
new file mode 100644
index 0000000000..fad9bba33f
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/n2cp.h
@@ -0,0 +1,702 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_N2CP_H
+#define _SYS_N2CP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/mdesc.h>
+#include <sys/crypto/common.h>
+#include <sys/crypto/spi.h>
+#include <sys/ncs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DRIVER "n2cp"
+#define N2CP_MANUFACTURER_ID "SUNWn2cp"
+
+#if defined(_KERNEL)
+
+#define FALSE 0
+#define TRUE 1
+
+#define BITS2BYTES(b) ((b) >> 3)
+#define BYTES2BITS(b) ((b) << 3)
+
+#define N_MBLKL(mp) ((uint64_t)(mp)->b_wptr - (uint64_t)(mp)->b_rptr)
+
+/*
+ * NCP Structures.
+ */
+typedef struct n2cp n2cp_t;
+typedef struct n2cp_minor n2cp_minor_t;
+typedef struct n2cp_listnode n2cp_listnode_t;
+typedef struct n2cp_request n2cp_request_t;
+typedef struct n2cp_stat n2cp_stat_t;
+typedef struct n2cp_block_ctx n2cp_block_ctx_t;
+typedef struct n2cp_hash_ctx n2cp_hash_ctx_t;
+typedef struct n2cp_hmac_ctx n2cp_hmac_ctx_t;
+
+
+#define N2CP_MAX_NCWQS 8
+#define N2CP_MAX_CPUS_PER_CWQ 8
+#define N2CP_MAX_HELPERTHREADS (N2CP_MAX_NCWQS * N2CP_MAX_CPUS_PER_CWQ)
+
+/*
+ * HW limitaions for Data and Key. For an input greater than 64KB, Driver will
+ * break up the input into 64KB blocks, and send the jobs to the hardware.
+ */
+#define CW_MAX_DATA_LEN (1 << 16) /* 64K */
+#define CW_MAX_KEY_LEN (1 << 8) /* 256 */
+
+#define CW_TYPE_INITIAL 1
+#define CW_TYPE_EXTENSION 2
+#define CW_TYPE_FINAL 3
+#define CW_TYPE_COMPLETE 4
+
+/*
+ * Defines for fields in Initial Control Word.
+ */
+#define CW_OP_SSL 16
+#define CW_OP_COPY 32
+#define CW_OP_ENCRYPT 64
+#define CW_OP_MAC_AUTH 65
+#define CW_OP_INLINE_BIT (1 << 7)
+
+#define CW_AUTH_MD5 1
+#define CW_AUTH_SHA1 2
+#define CW_AUTH_SHA256 3
+#define CW_AUTH_CRC32 4
+#define CW_AUTH_HMAC_MD5 5
+#define CW_AUTH_HMAC_SHA1 6
+#define CW_AUTH_HMAC_SHA256 7
+#define CW_AUTH_TCPCKSUM 8
+#define CW_AUTH_SSL_HMAC_MD5 9
+#define CW_AUTH_SSL_HMAC_SHA1 10
+#define CW_AUTH_SSL_HMAC_SHA256 11
+
+#define CW_ENC_ALGO_RC4WSTRM 0
+#define CW_ENC_ALGO_RC4WOSTRM 1
+#define CW_ENC_ALGO_DES 2
+#define CW_ENC_ALGO_3DES 3
+#define CW_ENC_ALGO_AES128 4
+#define CW_ENC_ALGO_AES192 5
+#define CW_ENC_ALGO_AES256 6
+
+#define CW_ENC_CHAIN_ECB 0
+#define CW_ENC_CHAIN_CBC 1
+#define CW_ENC_CHAIN_CFB 2
+#define CW_ENC_CHAIN_AESCTR 3
+
+#define CW_ENC_TYPE(a, c) ((((a) & 7) << 2) | ((c) & 3))
+
+#define CWQ_NENTRIES (1 << 9) /* 512 */
+#define CWQ_WRAPMASK (CWQ_NENTRIES - 1)
+
+/* CWS_ALIGNMENT is used as an alignment parameter to contig_mem_alloc */
+#define CWQ_ALIGNMENT 64
+#define CWQ_SLOTS_USED(q) (((q)->cq_tail - (q)->cq_head) & CWQ_WRAPMASK)
+#define CWQ_SLOTS_AVAIL(q) (CWQ_NENTRIES - CWQ_SLOTS_USED(q) - 1)
+#define CWQ_QINDEX_TO_QOFFSET(i) ((i) * sizeof (cwq_cw_t))
+#define CWQ_QOFFSET_TO_QINDEX(o) ((o) / sizeof (cwq_cw_t))
+#define CWQ_QINDEX_INCR(i) (((i) + 1) & CWQ_WRAPMASK)
+#define CWQ_QINDEX_IS_VALID(i) (((i) >= 0) && ((i) < CWQ_NENTRIES))
+
+#define N2CP_QTIMEOUT_SECONDS 15
+
+typedef struct cwq_cwb {
+ cwq_cw_t cb_cw;
+ struct cwq_cwb *cb_next;
+} cwq_cwb_t;
+
+typedef struct cwq_cwjob {
+ int cj_id;
+ kcondvar_t cj_cv;
+ boolean_t cj_pending; /* awaiting CWQ */
+ cwq_cwb_t *cj_cwb;
+ struct cwq_cwjob *cj_prev;
+ struct cwq_cwjob *cj_next;
+ void *cj_ctx; /* ptr to n2cp_request */
+} cwq_cwjob_t;
+
+typedef struct {
+ uint64_t cq_handle;
+ uint64_t cq_devino;
+ int cq_inum;
+ kmutex_t cq_lock;
+ int cq_id;
+ int cq_init;
+ int cq_busy_wait;
+ kcondvar_t cq_busy_cv;
+ cwq_cwjob_t **cq_jobs;
+ size_t cq_jobs_size;
+ void *cq_mem;
+ int cq_memsize;
+ cwq_cw_t *cq_first;
+ cwq_cw_t *cq_last;
+ cwq_cw_t *cq_head;
+ cwq_cw_t *cq_tail;
+ cwq_cwjob_t *cq_joblist;
+ int cq_joblistcnt;
+ struct {
+ uint64_t qks_njobs;
+ uint64_t qks_ncws;
+ uint64_t qks_qfull;
+ uint64_t qks_qbusy;
+ uint64_t qks_qfail;
+ uint64_t qks_nintr;
+ uint64_t qks_nintr_err;
+ uint64_t qks_nintr_jobs;
+ } cq_ks;
+} cwq_t;
+
+#define CWQ_STATE_ERROR (-1)
+#define CWQ_STATE_OFFLINE 0
+#define CWQ_STATE_ONLINE 1
+
+typedef struct {
+ int mm_cwqid;
+ int mm_cpulistsz;
+ int *mm_cpulist;
+ int mm_ncpus;
+ int mm_nextcpuidx;
+ /*
+ * Only protects mm_nextcpuidx field.
+ */
+ kmutex_t mm_lock;
+ /*
+ * xxx - maybe need RW lock for mm_state?
+ */
+ int mm_state; /* CWQ_STATE_... */
+
+ cwq_t mm_queue;
+} cwq_entry_t;
+
+typedef struct {
+ int mc_cpuid;
+ int mc_cwqid;
+ /*
+ * xxx - maybe need RW lock for mm_state?
+ * Mirrors mm_state in mau_entry_t. Duplicated
+ * for speed so we don't have search mau_entry
+ * table. Field rarely updated.
+ */
+ int mc_state; /* CWQ_STATE_... */
+} cpu_entry_t;
+
+typedef struct {
+ /*
+ * CWQ stuff
+ */
+ int m_cwqlistsz;
+ cwq_entry_t *m_cwqlist;
+ int m_ncwqs;
+ int m_nextcwqidx;
+ /*
+ * Only protects m_nextcwqidx field.
+ */
+ kmutex_t m_lock;
+
+ /*
+ * CPU stuff
+ */
+ int m_cpulistsz;
+ cpu_entry_t *m_cpulist;
+ int m_ncpus;
+} n2cp_cwq2cpu_map_t;
+
+#define MAX_FIXED_IV_WORDS 8
+typedef struct fixed_iv {
+ int ivsize;
+ uint32_t iv[MAX_FIXED_IV_WORDS];
+} fixed_iv_t;
+
+#define MD5_DIGESTSZ (4 * sizeof (uint32_t))
+#define SHA1_DIGESTSZ (5 * sizeof (uint32_t))
+#define SHA256_DIGESTSZ (8 * sizeof (uint32_t))
+#define MAX_DIGESTSZ (MAX_FIXED_IV_WORDS * sizeof (uint32_t))
+
+#define MAX_DATA_LEN 0x10000
+
+#define DES_KEY_LEN 8
+#define DES3_KEY_LEN 24
+#define DESBLOCK 8
+#define AES_MIN_KEY_LEN 16
+#define AES_MAX_KEY_LEN 32
+#define AESBLOCK 16
+#define MAXBLOCK AESBLOCK
+#define MAXVALUE AES_MAX_KEY_LEN
+
+#define RC4_MIN_KEY_LEN 1
+#define RC4_MAX_KEY_LEN 256
+
+/*
+ * We only support up to 64 counter bit
+ */
+#define MAX_CTR_BITS 64
+
+
+#define HMAC_MIN_KEY_LEN 1
+#define HMAC_MAX_KEY_LEN CW_MAX_KEY_LEN
+
+
+/*
+ * Some pkcs#11 defines as there are no pkcs#11 header files included.
+ */
+#define CKA_VALUE 0x00000011
+#define CKA_KEY_TYPE 0x00000100
+
+/*
+ * Request flags (n2cp_request_t.nr_flags).
+ */
+#define N2CP_SCATTER 0x01
+#define N2CP_GATHER 0x02
+
+/* define the mechanisms strings not defined in <sys/crypto/common.h> */
+#define SUN_CKM_SSL3_MD5_MAC "CKM_SSL3_MD5_MAC"
+#define SUN_CKM_SSL3_SHA1_MAC "CKM_SSL3_SHA1_MAC"
+
+#ifdef SSL3_SHA256_MAC_SUPPORT
+#define SUN_CKM_SSL3_SHA256_MAC "CKM_SSL3_SHA256_MAC"
+#endif
+
+/*
+ * XXX: Vendor defined version of CKM_AES_CTR. This lets us test AES_CTR
+ * from PKCS#11. Note: this is temporally added until CKM_AES_CTR is officially
+ * added to PKCS#11 spec.
+ */
+#define N2CP_CKM_AES_CTR "0x80001086"
+
+/*
+ * Scatter/gather checks.
+ */
+#define N2CP_SG_CONTIG 0x1 /* contiguous buffer */
+#define N2CP_SG_WALIGN 0x2 /* word aligned */
+#define N2CP_SG_PALIGN 0x4 /* page aligned */
+#define N2CP_SG_PCONTIG 0x8 /* physically contiguous buffer */
+
+
+/*
+ * Kstats.
+ */
+#define DS_DES 0
+#define DS_DES3 1
+#define DS_AES 2
+#define DS_MD5 3
+#define DS_SHA1 4
+#define DS_SHA256 5
+#define DS_MD5_HMAC 6
+#define DS_SHA1_HMAC 7
+#define DS_SHA256_HMAC 8
+#define DS_SSL_MD5_MAC 9
+#define DS_SSL_SHA1_MAC 10
+#define DS_SSL_SHA256_MAC 11
+#define DS_RC4 12
+#define DS_MAX 13
+
+struct n2cp_stat {
+ kstat_named_t ns_status;
+ kstat_named_t ns_algs[DS_MAX];
+ struct {
+ kstat_named_t ns_cwqid;
+ kstat_named_t ns_cwqhandle;
+ kstat_named_t ns_cwqstate;
+ kstat_named_t ns_submit;
+ kstat_named_t ns_cwcount;
+ kstat_named_t ns_qfull;
+ kstat_named_t ns_qbusy;
+ kstat_named_t ns_qupdate_failure;
+ kstat_named_t ns_nintr;
+ kstat_named_t ns_nintr_err;
+ kstat_named_t ns_nintr_jobs;
+ } ns_cwq[N2CP_MAX_NCWQS];
+};
+
+
+/*
+ * Linked-list linkage.
+ */
+struct n2cp_listnode {
+ n2cp_listnode_t *nl_next;
+ n2cp_listnode_t *nl_prev;
+};
+
+typedef enum n2cp_mech_type {
+ DES_CBC_MECH_INFO_TYPE, /* CKM_DES_CBC */
+ DES_ECB_MECH_INFO_TYPE, /* CKM_DES_ECB */
+ DES_CFB_MECH_INFO_TYPE, /* CKM_DES_CFB */
+ DES3_CBC_MECH_INFO_TYPE, /* CKM_DES3_CBC */
+ DES3_ECB_MECH_INFO_TYPE, /* CKM_DES3_ECB */
+ DES3_CFB_MECH_INFO_TYPE, /* CKM_DES3_CFB */
+ AES_CBC_MECH_INFO_TYPE, /* CKM_AES_CBC */
+ AES_ECB_MECH_INFO_TYPE, /* CKM_AES_ECB */
+ AES_CTR_MECH_INFO_TYPE, /* CKM_AES_CTR */
+ RC4_WSTRM_MECH_INFO_TYPE, /* CKM_RC4 */
+ RC4_WOSTRM_MECH_INFO_TYPE, /* CKM_RC4 w/o stream */
+ MD5_MECH_INFO_TYPE, /* CKM_MD5 */
+ SHA1_MECH_INFO_TYPE, /* CKM_SHA_1 */
+ SHA256_MECH_INFO_TYPE, /* CKM_SHA256 */
+ MD5_HMAC_MECH_INFO_TYPE, /* CKM_MD5_HMAC */
+ SHA1_HMAC_MECH_INFO_TYPE, /* CKM_SHA_1_HMAC */
+ SHA256_HMAC_MECH_INFO_TYPE, /* CKM_SHA256_HMAC */
+ MD5_HMAC_GENERAL_MECH_INFO_TYPE, /* CKM_MD5_HMAC_GENERAL */
+ SHA1_HMAC_GENERAL_MECH_INFO_TYPE, /* CKM_SHA_1_HMAC_GENERAL */
+ SHA256_HMAC_GENERAL_MECH_INFO_TYPE, /* CKM_SHA256_HMAC_GENERAL */
+ SSL3_MD5_MAC_MECH_INFO_TYPE, /* CKM_SSL3_MD5_MAC */
+ SSL3_SHA1_MAC_MECH_INFO_TYPE, /* CKM_SSL3_SHA1_MAC */
+ SSL3_SHA256_MAC_MECH_INFO_TYPE, /* CKM_SSL3_SHA256_MAC */
+ /* Vendor Defined Mechanism */
+ N2CP_AES_CTR_MECH_INFO_TYPE /* CKM_AES_CTR */
+} n2cp_mech_type_t;
+
+/*
+ * Operation Flags: These flags are used internally within driver to specify
+ * the kind of operation for a job.
+ */
+#define N2CP_CMD_MASK 0x0000ffff
+#define N2CP_OP_ENCRYPT 0x00010000
+#define N2CP_OP_DECRYPT 0x00020000
+#define N2CP_OP_SIGN 0x00040000
+#define N2CP_OP_VERIFY 0x00080000
+#define N2CP_OP_DIGEST 0x00100000
+#define N2CP_OP_SINGLE 0x00200000
+#define N2CP_OP_MULTI 0x00400000
+
+/*
+ * Mechanism Specific Contexts
+ */
+
+typedef struct {
+ uchar_t key[RC4_MAX_KEY_LEN];
+ uchar_t i, j;
+} rc4_key_t;
+
+struct n2cp_block_ctx {
+ union {
+ uchar_t val[MAXVALUE];
+ rc4_key_t rc4val;
+ } keystruct;
+ int keylen;
+ int ivlen;
+ uchar_t iv[MAXBLOCK];
+ int nextivlen;
+ uchar_t nextiv[MAXBLOCK];
+ int ctrbits; /* used for AES_CTR */
+ int residlen;
+ char resid[MAXBLOCK];
+ int lastblocklen;
+ char lastblock[MAXBLOCK];
+};
+
+#define keyvalue keystruct.val
+#define rc4keyvalue keystruct.rc4val
+
+
+struct n2cp_hash_ctx {
+ uint32_t hashsz;
+ uint32_t iv[MAX_FIXED_IV_WORDS];
+};
+
+struct n2cp_hmac_ctx {
+ uint32_t hashsz;
+ uint32_t signlen;
+ uint32_t iv[MAX_FIXED_IV_WORDS];
+ int keylen;
+ uchar_t keyval[CW_MAX_KEY_LEN];
+};
+
+
+/*
+ * Work structure.
+ * Contains everything we need to submit the job, and everything we
+ * need to notify caller and release resources.
+ */
+typedef union {
+ n2cp_block_ctx_t blockctx;
+ n2cp_hash_ctx_t hashctx;
+ n2cp_hmac_ctx_t hmacctx;
+} nr_ctx_t;
+
+struct n2cp_request {
+ n2cp_listnode_t nr_linkage; /* must be at the top */
+ uint32_t nr_cmd; /* N2CP_OP | MECH_INFO_TYPE */
+ uint16_t nr_pkt_length;
+ crypto_req_handle_t nr_kcfreq;
+ n2cp_t *nr_n2cp;
+ int nr_errno;
+ /*
+ * Consumer's I/O buffers.
+ */
+ crypto_data_t *nr_in;
+ crypto_data_t *nr_out;
+ crypto_data_t nr_tmpin;
+
+ /*
+ * CWB
+ */
+ cwq_cwb_t *nr_cwb;
+ int nr_cwcnt;
+
+ nr_ctx_t *nr_context;
+ int nr_context_sz;
+ int nr_blocksz;
+
+ /*
+ * Callback.
+ */
+ void (*nr_callback)(n2cp_request_t *);
+ /*
+ * Other stuff.
+ */
+ uchar_t *nr_in_buf;
+ uchar_t *nr_out_buf;
+ uint32_t nr_flags;
+ int nr_resultlen;
+ /*
+ * Statistics.
+ */
+ int nr_job_stat;
+};
+
+struct n2cp {
+ int n_hvapi_major_version;
+ int n_hvapi_minor_version;
+ kmutex_t n_lock;
+ dev_info_t *n_dip;
+
+ ddi_taskq_t *n_taskq;
+ ddi_taskq_t *n_intrtaskq;
+
+ unsigned n_flags; /* dev state flags */
+
+ kstat_t *n_ksp;
+ uint64_t n_stats[DS_MAX];
+
+ ddi_intr_handle_t *n_htable;
+ int n_intr_cid[N2CP_MAX_NCWQS];
+ int n_intr_cnt;
+ size_t n_intr_size;
+ uint_t n_intr_pri;
+
+ size_t n_reqctx_sz;
+ ulong_t n_pagesize;
+ crypto_kcf_provider_handle_t n_prov;
+
+ kmutex_t n_freereqslock;
+ n2cp_listnode_t n_freereqs; /* available requests */
+
+ kmutex_t n_ctx_list_lock;
+ n2cp_listnode_t n_ctx_list;
+
+ md_t *n_mdp;
+ n2cp_cwq2cpu_map_t n_cwqmap;
+};
+
+/* CK_AES_CTR_PARAMS provides the parameters to the CKM_AES_CTR mechanism */
+typedef struct CK_AES_CTR_PARAMS {
+ ulong_t ulCounterBits;
+ uint8_t iv[AESBLOCK];
+} CK_AES_CTR_PARAMS;
+
+typedef struct CK_AES_CTR_PARAMS32 {
+ uint32_t ulCounterBits;
+ uint8_t iv[AESBLOCK];
+} CK_AES_CTR_PARAMS32;
+
+
+/*
+ * Priority of task threads used for handling interrupts.
+ */
+#define N2CP_INTRTASK_PRI 80
+
+#endif /* _KERNEL */
+
+/*
+ * Miscellaneous defines.
+ */
+#define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1))
+#define ROUNDDOWN(a, n) ((a) & ~((n) - 1))
+#define PAD32(x) ROUNDUP(x, sizeof (uint32_t))
+#define PADAES(x) ROUNDUP(x, AESBLOCK)
+#define BYTES_TO_UINT64(n) \
+ (((n) + (sizeof (uint64_t) - 1)) / sizeof (uint64_t))
+#define BYTES_TO_UINT32(n) \
+ (((n) + (sizeof (uint32_t) - 1)) / sizeof (uint32_t))
+
+#if defined(_KERNEL)
+
+#if defined(DEBUG)
+
+#define DWARN 0x00000001
+#define DMA_ARGS 0x00000002
+#define DMA_LDST 0x00000004
+#define DNCS_QTAIL 0x00000008
+#define DATTACH 0x00000010
+#define DMD 0x00000020
+#define DHV 0x00000040
+#define DINTR 0x00000080
+#define DMOD 0x00000100 /* _init/_fini/_info/attach/detach */
+#define DCHATTY 0x00000400
+#define DALL 0xFFFFFFFF
+
+void n2cp_dprintf(n2cp_t *, int, const char *, ...);
+void n2cp_dumphex(void *, int);
+int n2cp_dflagset(int);
+
+#define DBG0 n2cp_dprintf
+#define DBG1 n2cp_dprintf
+#define DBG2 n2cp_dprintf
+#define DBG3 n2cp_dprintf
+#define DBG4 n2cp_dprintf
+
+#else /* !defined(DEBUG) */
+
+#define DBG0(vca, lvl, fmt)
+#define DBG1(vca, lvl, fmt, arg1)
+#define DBG2(vca, lvl, fmt, arg1, arg2)
+#define DBG3(vca, lvl, fmt, arg1, arg2, arg3)
+#define DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4)
+
+
+#endif /* !defined(DEBUG) */
+
+/*
+ * n2cp.c
+ */
+cwq_cwb_t *n2cp_cwb_allocate();
+void n2cp_cwb_free(cwq_cwb_t *);
+int n2cp_start(n2cp_t *, n2cp_request_t *);
+void *n2_contig_alloc(int);
+void n2_contig_free(void *, int);
+
+
+/*
+ * n2cp_debug.c
+ */
+void n2cp_error(n2cp_t *, const char *, ...);
+void n2cp_diperror(dev_info_t *, const char *, ...);
+void n2cp_dipverror(dev_info_t *, const char *, va_list);
+void n2cp_dump_cwb(cwq_cw_t *cw);
+
+
+
+/*
+ * n2cp_kstat.c
+ */
+void n2cp_ksinit(n2cp_t *);
+void n2cp_ksdeinit(n2cp_t *);
+
+/*
+ * n2cp_kcf.c
+ */
+int n2cp_init(n2cp_t *);
+int n2cp_uninit(n2cp_t *);
+void n2cp_rmqueue(n2cp_listnode_t *);
+n2cp_request_t *n2cp_getreq(n2cp_t *, int);
+void n2cp_freereq(n2cp_request_t *);
+void n2cp_destroyreq(n2cp_request_t *);
+caddr_t n2cp_bufdaddr(crypto_data_t *);
+int n2cp_gather(crypto_data_t *, char *, int);
+int n2cp_gather_zero_pad(crypto_data_t *, caddr_t, size_t, int);
+int n2cp_scatter(const char *, crypto_data_t *, int);
+int n2cp_sgcheck(n2cp_t *, crypto_data_t *, int);
+
+int n2cp_attr_lookup_uint8_array(crypto_object_attribute_t *, uint_t,
+ uint64_t, void **, unsigned int *);
+crypto_object_attribute_t *
+ n2cp_find_attribute(crypto_object_attribute_t *, uint_t, uint64_t);
+char *n2cp_get_dataaddr(crypto_data_t *);
+void n2cp_setresid(crypto_data_t *, int);
+void n2cp_getbufbytes(crypto_data_t *, int, int, char *);
+uint16_t n2cp_padhalf(int);
+uint16_t n2cp_padfull(int);
+
+/*
+ * n2cp_hash.c
+ */
+int n2cp_hashatomic(n2cp_t *, crypto_mechanism_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+int n2cp_hashinit(crypto_ctx_t *, crypto_mechanism_t *);
+int n2cp_hash(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+
+/*
+ * n2cp_block.c
+ */
+int n2cp_blockinit(crypto_ctx_t *, crypto_mechanism_t *,
+ crypto_key_t *, int);
+int n2cp_block(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+int n2cp_blockupdate(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t *);
+int n2cp_blockfinal(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t *);
+int n2cp_blockatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t, int);
+void n2cp_clean_blockctx(n2cp_request_t *);
+int n2cp_aes_ctr_allocmech(crypto_mechanism_t *, crypto_mechanism_t *,
+ int *, int);
+int n2cp_aes_ctr_freemech(crypto_mechanism_t *);
+
+
+/*
+ * n2cp_hmac.c
+ */
+int n2cp_hmacinit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *);
+int n2cp_hmac_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+int n2cp_hmac_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+int n2cp_hmac_signatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+int n2cp_hmac_verifyatomic(n2cp_t *, crypto_mechanism_t *, crypto_key_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+void n2cp_clean_hmacctx(n2cp_request_t *);
+int n2cp_ssl3_sha1_mac_signatomic(n2cp_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+int n2cp_ssl3_sha1_mac_verifyatomic(n2cp_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+
+/*
+ * n2cp_md.c
+ */
+int n2cp_init_cwq2cpu_map(n2cp_t *);
+void n2cp_deinit_cwq2cpu_map(n2cp_t *);
+int n2cp_map_cwq_to_cpu(n2cp_t *, int);
+int n2cp_map_cpu_to_cwq(n2cp_t *, int);
+int n2cp_map_nextcwq(n2cp_t *);
+cwq_entry_t *n2cp_map_findcwq(n2cp_t *, int);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_N2CP_H */
diff --git a/usr/src/uts/sun4v/sys/n2rng.h b/usr/src/uts/sun4v/sys/n2rng.h
new file mode 100644
index 0000000000..9d53593836
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/n2rng.h
@@ -0,0 +1,278 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_N2RNG_H
+#define _SYS_N2RNG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* skip following stuff when included in n2rng_hcall.s */
+#ifndef _ASM
+#include <sys/types.h>
+#include <sys/mutex.h>
+#include <sys/ksynch.h>
+#include <sys/sunddi.h>
+#include <sys/param.h>
+#include <sys/crypto/common.h>
+#include <sys/crypto/spi.h>
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * RNG HV API version definitions.
+ */
+#define RNG_MAJOR_VER 1
+#define RNG_MINOR_VER 0
+
+#define HV_RNG_GET_DIAG_CONTROL 0x130
+#define HV_RNG_CTL_READ 0x131
+#define HV_RNG_CTL_WRITE 0x132
+#define HV_RNG_DATA_READ_DIAG 0x133
+#define HV_RNG_DATA_READ 0x134
+
+#define CTL_STATE_UNCONFIGURED 0
+#define CTL_STATE_CONFIGURED 1
+#define CTL_STATE_HEALTHCHECK 2
+#define CTL_STATE_ERROR 3
+
+#define NRNGCTL 4
+#define N2RNG_MAX_READ (128 * 1024) /* 128K bytes */
+
+#define DRIVER "n2rng"
+#define N2RNG_MANUFACTURER_ID "SUNWn2rng"
+
+
+#ifndef _ASM
+
+typedef union n2rngctl {
+ uint64_t word;
+ struct {
+ uint64_t rnc_res : 39;
+ uint64_t rnc_cnt : 16;
+ uint64_t rnc_bypass : 1;
+ uint64_t rnc_vcoctl : 2;
+ uint64_t rnc_anlg_sel : 2;
+ uint64_t rnc_mode : 1;
+ uint64_t rnc_selbits : 3;
+ } fields;
+} n2rng_ctl_t;
+
+typedef struct {
+ n2rng_ctl_t ctlwds[NRNGCTL];
+} n2rng_setup_t;
+
+#if defined(_KERNEL)
+
+/*
+ * Our contiguous memory alignment requirement is
+ * only for 8 bytes, however contig mem allocation
+ * routines requirement minimum of 64.
+ */
+#define CONTIG_ALIGNMENT 64
+/*
+ * Returns 1 only if the address range of a variable of type type at
+ * ptr falls entirely on one page. Based on page size of 4K. May
+ * give some false negatives on larger page sizes.
+ */
+#define CONTIGUOUS(ptr, type) \
+ (((((uint64_t)(ptr)) ^ ((uint64_t)(ptr) + sizeof (type) -1)) \
+ & PAGEMASK) == 0)
+
+/*
+ * The RNG hardware can send certain internal analog signals to an
+ * external pin on the chip. Setting the rnc_anlg_sel bit to
+ * N2RNG_NOANALOGOUT deselects all analog signals (perhaps selects
+ * ground). Choosing any other value would aid an attacker with
+ * physical access to the chip.
+ */
+#define N2RNG_NOANALOGOUT 0x2
+
+/*
+ * There can only be N2_RNG_FIPS_INSTANCES concurrent RNG requsts from
+ * the framework. Making this value large helps benchmarks. It
+ * should probably come from a conf file, but for now it is hard
+ * coded. The code computes i % N2RNG_FIPS_INSTANCES, which is more
+ * efficient when N2RNG_FIPS_INSTANCES is a power of 2.
+ */
+#define N2RNG_FIPS_INSTANCES 8
+
+typedef struct fipsrandomstruct fipsrandomstruct_t;
+struct fipsrandomstruct {
+ kmutex_t mtx;
+ uint64_t entropyhunger; /* RNGs generated with no entropy */
+ uint32_t XKEY[6]; /* one extra word for getentropy */
+};
+
+typedef struct {
+ /*
+ * volatile, since it is not protected by a mutex. (That is
+ * okay since it is operated on and accessed via atomic ops.)
+ */
+ volatile unsigned int fips_round_robin_j;
+ fipsrandomstruct_t fipsarray[N2RNG_FIPS_INSTANCES];
+} fips_ensemble_t;
+
+#define N2RNG_FAILED 0x1 /* for n_flags; used by kstat */
+
+#define DS_RNGBYTES 0
+#define DS_RNGJOBS 1
+#define DS_RNGHEALTHCHECKS 2
+#define DS_MAX 3
+
+#define N2RNG_NOSC 3
+#define N2RNG_BIASBITS 2
+#define N2RNG_NBIASES (1 << N2RNG_BIASBITS)
+#define N2RNG_CTLOPS (N2RNG_OSC + 1)
+
+typedef struct {
+ uint64_t numvals;
+ uint64_t H1; /* in bits per bit << LOG_VAL_SCALE */
+ uint64_t H2;
+ uint64_t Hinf;
+} n2rng_osc_perf_t;
+
+typedef n2rng_osc_perf_t n2rng_osc_perf_table_t[N2RNG_NOSC][N2RNG_NBIASES];
+
+
+typedef struct n2rng {
+ kmutex_t n_lock;
+ dev_info_t *n_dip;
+ minor_t n_minor;
+ unsigned n_flags; /* dev state flags */
+ kstat_t *n_ksp;
+ uint64_t n_stats[DS_MAX];
+ crypto_kcf_provider_handle_t n_prov;
+ fips_ensemble_t n_frs;
+ n2rng_osc_perf_table_t n_perftable;
+ n2rng_setup_t n_preferred_config;
+ kmutex_t n_health_check_mutex;
+ time_t n_last_health_time;
+ uint64_t n_rng_state; /* as last known in this drvr. */
+ uint64_t n_sticks_per_usec;
+ uint64_t n_anlg_settle_cycles;
+} n2rng_t;
+
+
+typedef struct n2rng_stat n2rng_stat_t;
+struct n2rng_stat {
+ kstat_named_t ns_status;
+ kstat_named_t ns_algs[DS_MAX];
+};
+
+#define RNG_MODE_NORMAL 1
+#define RNG_MODE_DIAGNOSTIC 0
+
+#define RNG_CTL_SETTLE_NS 2000000 /* nanoseconds */
+#define RNG_DIAG_CHUNK_SIZE (N2RNG_MAX_READ / 8) /* as words */
+#define RNG_MAX_DATA_READ_ATTEMPTS 100
+#define RNG_DEFAULT_ACCUMULATE_CYCLES 4000
+#define RNG_RETRY_HLCHK_USECS 100000 /* retry every .1 seconds */
+
+#define LOG_ARG_SCALE 49
+#define LOG_VAL_SCALE 32
+
+
+void n2rng_sort(uint64_t *data, int log2_size);
+int n2rng_noise_gen_preferred(n2rng_t *n2rng);
+int n2rng_check_set(n2rng_t *n2rng);
+int n2rng_collect_diag_bits(n2rng_t *n2rng, n2rng_setup_t *collect_setupp,
+ void *buffer, int numbytes, n2rng_setup_t *exit_setupp,
+ uint64_t exitstate);
+int n2rng_getentropy(n2rng_t *n2rng, void *buffer, size_t size);
+int n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp);
+void n2rng_fips_random_fini(fipsrandomstruct_t *frsp);
+int n2rng_do_health_check(n2rng_t *n2rng);
+void n2rng_renyi_entropy(uint64_t *buffer, int log2samples,
+ n2rng_osc_perf_t *metricp);
+
+
+
+
+#if defined(DEBUG)
+
+#define DWARN 0x00000001
+#define DMA_ARGS 0x00000002
+#define DMA_LDST 0x00000004
+#define DNCS_QTAIL 0x00000008
+#define DATTACH 0x00000010
+#define DMOD 0x00000040 /* _init/_fini/_info/attach/detach */
+#define DENTRY 0x00000080 /* crypto routine entry/exit points */
+#define DCHATTY 0x00000100
+#define DALL 0xFFFFFFFF
+
+#define DBG0 n2rng_dprintf
+#define DBG1 n2rng_dprintf
+#define DBG2 n2rng_dprintf
+#define DBG3 n2rng_dprintf
+#define DBG4 n2rng_dprintf
+#define DBG5 n2rng_dprintf
+#define DBG6 n2rng_dprintf
+#define DBGCALL(flag, func) { if (n2rng_dflagset(flag)) (void) func; }
+
+void n2rng_dprintf(n2rng_t *, int, const char *, ...);
+void n2rng_dumphex(void *, int);
+int n2rng_dflagset(int);
+
+#else /* !defined(DEBUG) */
+
+#define DBG0(vca, lvl, fmt)
+#define DBG1(vca, lvl, fmt, arg1)
+#define DBG2(vca, lvl, fmt, arg1, arg2)
+#define DBG3(vca, lvl, fmt, arg1, arg2, arg3)
+#define DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4)
+#define DBG5(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5)
+#define DBG6(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
+#define DBGCALL(flag, func)
+
+#endif /* !defined(DEBUG) */
+
+/*
+ * n2rng_debug.c
+ */
+void n2rng_error(n2rng_t *, const char *, ...);
+void n2rng_diperror(dev_info_t *, const char *, ...);
+void n2rng_dipverror(dev_info_t *, const char *, va_list);
+
+uint64_t hv_rng_get_diag_control(void);
+uint64_t hv_rng_read_ctl(uint64_t ctlregs_pa, uint64_t *state,
+ uint64_t *tdelta);
+uint64_t hv_rng_ctl_write(uint64_t ctlregs_pa,
+ uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta);
+uint64_t hv_rng_data_read_diag(uint64_t data_pa,
+ size_t datalen, uint64_t *tdelta);
+uint64_t hv_rng_data_read(uint64_t data_pa, uint64_t *tdelta);
+
+#endif /* _KERNEL */
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_N2RNG_H */
diff --git a/usr/src/uts/sun4v/sys/ncp.h b/usr/src/uts/sun4v/sys/ncp.h
index e9ba364556..1fcff12dc2 100644
--- a/usr/src/uts/sun4v/sys/ncp.h
+++ b/usr/src/uts/sun4v/sys/ncp.h
@@ -49,11 +49,27 @@ extern "C" {
#define FALSE 0
#define TRUE 1
-#define NCP_MAX_NMAUS 8
-#define NCP_MAX_CPUS_PER_MAU 4
-#define NCP_CPUID2MAUID(c) ((c) / NCP_MAX_CPUS_PER_MAU)
+#define N_MBLKL(mp) ((uint64_t)(mp)->b_wptr - (uint64_t)(mp)->b_rptr)
-#define NCP_MAX_HELPERTHREADS (NCP_MAX_NMAUS * NCP_MAX_CPUS_PER_MAU)
+#define NCP_N1_MAX_NMAUS 8
+#define NCP_N1_MAX_CPUS_PER_MAU 4
+#define NCP_N2_MAX_NMAUS 8
+#define NCP_N2_MAX_CPUS_PER_MAU 8
+#define NCP_MAX_MAX_NMAUS NCP_N2_MAX_NMAUS
+
+#define NCP_CPUID2MAUID(n, c) ((c) / (n)->n_max_cpus_per_mau)
+
+#define NCP_MAX_HELPERTHREADS(n) ((n)->n_max_nmaus * \
+ (n)->n_max_cpus_per_mau)
+
+#define NCP_BINDNAME_N1 "SUNW,sun4v-ncp"
+#define NCP_BINDNAME_N2 "SUNW,n2-mau"
+
+typedef enum {
+ NCP_CPU_UNKNOWN,
+ NCP_CPU_N1,
+ NCP_CPU_N2
+} ncp_binding_t;
/*
* These are constants. Do not change them.
@@ -253,16 +269,10 @@ struct ncp_stat {
kstat_named_t ns_nintr;
kstat_named_t ns_nintr_err;
kstat_named_t ns_nintr_jobs;
- } ns_mau[NCP_MAX_NMAUS];
+ } ns_mau[NCP_MAX_MAX_NMAUS];
};
/*
- * Device flags (ncp_t.ncp_flags)
- */
-#define NCP_FAILED 0x1
-#define NCP_POWERMGMT 0x4
-
-/*
* IMPORTANT:
* NCP_MAQUEUE_NENTRIES *must* be a power-of-2.
* requirement: sizeof (ncs_hvdesc_t) == 64
@@ -299,6 +309,7 @@ struct ncp_desc {
typedef struct ncp_descjob {
int dj_id;
kcondvar_t dj_cv;
+ boolean_t dj_pending; /* awaiting MAU */
ncp_desc_t *dj_jobp;
struct ncp_descjob *dj_prev;
struct ncp_descjob *dj_next;
@@ -308,7 +319,7 @@ typedef struct ncp_descjob {
* nmq_head, nmq_tail = indexes into nmq_desc[].
*/
typedef struct {
- uint64_t nmq_mauhandle;
+ uint64_t nmq_handle;
uint64_t nmq_devino;
int nmq_inum;
int nmq_mauid;
@@ -395,24 +406,24 @@ typedef struct {
struct ncp {
uint_t n_hvapi_major_version;
uint_t n_hvapi_minor_version;
+ ncp_binding_t n_binding;
+ char *n_binding_name;
kmutex_t n_lock;
kmem_cache_t *n_ds_cache;
kmem_cache_t *n_mactl_cache;
kmem_cache_t *n_mabuf_cache;
dev_info_t *n_dip;
- minor_t n_minor;
ddi_taskq_t *n_taskq;
- unsigned n_flags; /* dev state flags */
+ int n_max_nmaus;
+ int n_max_cpus_per_mau;
kstat_t *n_ksp;
- kstat_t *n_intrstats;
u_longlong_t n_stats[DS_MAX];
ddi_intr_handle_t *n_htable;
- int n_intr_mid[NCP_MAX_NMAUS];
- int n_intr_type;
+ int n_intr_mid[NCP_MAX_MAX_NMAUS];
int n_intr_cnt;
size_t n_intr_size;
uint_t n_intr_pri;
diff --git a/usr/src/uts/sun4v/sys/ncs.h b/usr/src/uts/sun4v/sys/ncs.h
index 93c5a9a711..f8c468eff9 100644
--- a/usr/src/uts/sun4v/sys/ncs.h
+++ b/usr/src/uts/sun4v/sys/ncs.h
@@ -32,6 +32,10 @@
extern "C" {
#endif
+#ifndef _ASM
+#include <sys/mutex.h>
+#endif /* !_ASM */
+
/*
* NCS HV API v1.0
*/
@@ -59,17 +63,83 @@ typedef uint64_t ma_np_t;
*/
union ma_ctl {
uint64_t value;
- struct {
- uint64_t reserved1:50;
- uint64_t invert_parity:1;
- uint64_t thread:2;
- uint64_t busy:1;
- uint64_t interrupt:1;
- uint64_t operation:3;
- uint64_t length:6;
+ union {
+ struct {
+ uint64_t reserved1:50;
+ uint64_t invert_parity:1;
+ uint64_t thread:2;
+ uint64_t busy:1;
+ uint64_t interrupt:1;
+ uint64_t operation:3;
+ uint64_t length:6;
+ } n1;
+ struct {
+ uint64_t reserved0:38;
+ uint64_t ptymask:2;
+ uint64_t reserved1:1;
+ uint64_t hwerror:1;
+ uint64_t invalidop:1;
+ uint64_t thread:3;
+ uint64_t interrupt:1;
+ uint64_t busy:1;
+ uint64_t reserved3:3;
+ uint64_t operation:5;
+ uint64_t length:8;
+ } n2;
} bits;
};
-#endif /* !_ASM */
+
+
+typedef struct {
+ union {
+ struct {
+ uint64_t _cw_op :8;
+ uint64_t _cw_enc :1;
+ uint64_t _cw_sob :1;
+ uint64_t _cw_eob :1;
+ uint64_t _cw_resv1 :3;
+ uint64_t _cw_sfas :1;
+ uint64_t _cw_intr :1;
+ uint64_t _cw_hlen :8;
+ uint64_t _cw_strand_id :3;
+ uint64_t _cw_auth_type :5;
+ uint64_t _cw_enc_type :8;
+ uint64_t _cw_hmac_keylen :8;
+ uint64_t _cw_length :16;
+ } _s;
+ uint64_t _cw_ctlbits;
+ } _u;
+ uint64_t cw_src_addr;
+ uint64_t cw_auth_key_addr;
+ uint64_t cw_auth_iv_addr;
+ uint64_t cw_final_auth_state_addr;
+ uint64_t cw_enc_key_addr;
+ uint64_t cw_enc_iv_addr;
+ union {
+ uint64_t _cw_dst_addr;
+ uint64_t _cw_csr;
+ } _ux;
+} cwq_cw_t;
+
+#define cw_op _u._s._cw_op
+#define cw_enc _u._s._cw_enc
+#define cw_sob _u._s._cw_sob
+#define cw_eob _u._s._cw_eob
+#define cw_resv1 _u._s._cw_resv1
+#define cw_sfas _u._s._cw_sfas
+#define cw_intr _u._s._cw_intr
+#define cw_hlen _u._s._cw_hlen
+#define cw_resv2 _u._s._cw_resv2
+#define cw_strand_id _u._s._cw_strand_id
+#define cw_auth_type _u._s._cw_auth_type
+#define cw_enc_type _u._s._cw_enc_type
+#define cw_hmac_keylen _u._s._cw_hmac_keylen
+#define cw_length _u._s._cw_length
+#define cw_ctlbits _u._cw_ctlbits
+#define cw_dst_addr _ux._cw_dst_addr
+#define cw_csr _ux._cw_csr
+
+#endif /* _ASM */
/* Values for ma_ctl operation field */
#define MA_OP_LOAD 0x0
@@ -116,10 +186,6 @@ union ma_ma {
* NCS API definitions
*/
-#ifndef _ASM
-#include <sys/mutex.h>
-#endif /* !_ASM */
-
/*
* NCS HV API v1.0 definitions (PSARC/2005/125)
*/
@@ -132,14 +198,13 @@ union ma_ma {
/*
* The following are parameters to the NCS_QTAIL_UPDATE call:
*
- * NCS_SYNC Perform MA operations synchronously,
+ * NCS_SYNC Perform MA/SPU operations synchronously,
* i.e. wait for each enqueued operation
* to complete before progressing to
* next one.
- * NCS_ASYNC Perform MA operations asynchronously,
- * i.e. kick off the next MA operation
+ * NCS_ASYNC Perform MA/SPU operations asynchronously,
+ * i.e. kick off the next MA/SPU operation
* without waiting for its completion.
- * XXX - not supported yet.
*/
#define NCS_SYNC 0
#define NCS_ASYNC 1
@@ -248,7 +313,6 @@ extern uint64_t hv_ncs_gettail(uint64_t, uint64_t *);
extern uint64_t hv_ncs_settail(uint64_t, uint64_t);
extern uint64_t hv_ncs_qhandle_to_devino(uint64_t, uint64_t *);
extern uint64_t hv_ncs_sethead_marker(uint64_t, uint64_t);
-extern uint64_t hv_ncs_intr_clrstate(uint64_t);
#endif /* !_ASM */
#ifdef __cplusplus
diff --git a/usr/src/uts/sun4v/sys/niagara2regs.h b/usr/src/uts/sun4v/sys/niagara2regs.h
new file mode 100644
index 0000000000..3113597e39
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/niagara2regs.h
@@ -0,0 +1,124 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NIAGARA2REGS_H
+#define _SYS_NIAGARA2REGS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MB(n) ((n) * 1024 * 1024)
+
+#define L2CACHE_SIZE MB(4)
+#define L2CACHE_LINESIZE 64
+#define L2CACHE_ASSOCIATIVITY 16
+
+#define NIAGARA2_HSVC_MAJOR 1
+#define NIAGARA2_HSVC_MINOR 0
+
+/* PIC overflow range is -16 to -1 */
+#define PIC_IN_OV_RANGE(x) (((uint32_t)x >= 0xfffffff0) ? 1 : 0)
+
+/*
+ * Niagara2 SPARC Performance Instrumentation Counter
+ */
+#define PIC0_MASK (((uint64_t)1 << 32) - 1) /* pic0 in bits 31:0 */
+#define PIC1_SHIFT 32 /* pic1 in bits 64:32 */
+
+/*
+ * Niagara2 SPARC Performance Control Register
+ */
+#define CPC_NIAGARA2_PCR_PRIVPIC_SHIFT 0
+#define CPC_NIAGARA2_PCR_SYS_SHIFT 1
+#define CPC_NIAGARA2_PCR_USR_SHIFT 2
+#define CPC_NIAGARA2_PCR_HPRIV_SHIFT 3
+#define CPC_NIAGARA2_PCR_TOE0_SHIFT 4
+#define CPC_NIAGARA2_PCR_TOE1_SHIFT 5
+
+#define CPC_COUNT_HPRIV (1ull << CPC_NIAGARA2_PCR_HPRIV_SHIFT)
+#define CPC_COUNT_TOE0 (1ull << CPC_NIAGARA2_PCR_TOE0_SHIFT)
+#define CPC_COUNT_TOE1 (1ull << CPC_NIAGARA2_PCR_TOE1_SHIFT)
+
+#define CPC_NIAGARA2_PCR_PIC0_SHIFT 6
+#define CPC_NIAGARA2_PCR_PIC1_SHIFT 19
+#define CPC_NIAGARA2_PCR_PIC0_MASK UINT64_C(0xfff)
+#define CPC_NIAGARA2_PCR_PIC1_MASK UINT64_C(0xfff)
+
+#define CPC_NIAGARA2_PCR_OV0_MASK UINT64_C(0x40000)
+#define CPC_NIAGARA2_PCR_OV1_MASK UINT64_C(0x80000000)
+#define CPC_NIAGARA2_PCR_OV0_SHIFT 18
+#define CPC_NIAGARA2_PCR_OV1_SHIFT 30
+
+/*
+ * Hypervisor FAST_TRAP API function numbers to get/set DRAM
+ * performance counters
+ */
+#define HV_NIAGARA2_GETPERF 0x104
+#define HV_NIAGARA2_SETPERF 0x105
+
+/*
+ * Niagara2 DRAM performance counters
+ */
+#define NIAGARA_DRAM_BANKS 0x4
+
+#define NIAGARA_DRAM_PIC0_SEL_SHIFT 0x4
+#define NIAGARA_DRAM_PIC1_SEL_SHIFT 0x0
+
+#define NIAGARA_DRAM_PIC0_SHIFT 0x20
+#define NIAGARA_DRAM_PIC0_MASK 0x7fffffff
+#define NIAGARA_DRAM_PIC1_SHIFT 0x0
+#define NIAGARA_DRAM_PIC1_MASK 0x7fffffff
+
+/*
+ * SPARC/DRAM performance counter register numbers for HV_NIAGARA2_GETPERF
+ * and HV_NIAGARA2_SETPERF
+ */
+#define HV_NIAGARA_SPARC_CTL 0x0
+#define HV_NIAGARA_DRAM_CTL0 0x1
+#define HV_NIAGARA_DRAM_COUNT0 0x2
+#define HV_NIAGARA_DRAM_CTL1 0x3
+#define HV_NIAGARA_DRAM_COUNT1 0x4
+#define HV_NIAGARA_DRAM_CTL2 0x5
+#define HV_NIAGARA_DRAM_COUNT2 0x6
+#define HV_NIAGARA_DRAM_CTL3 0x7
+#define HV_NIAGARA_DRAM_COUNT3 0x8
+
+#ifndef _ASM
+/*
+ * prototypes for hypervisor interface to get/set SPARC and DRAM
+ * performance counters
+ */
+extern uint64_t hv_niagara_setperf(uint64_t regnum, uint64_t val);
+extern uint64_t hv_niagara_getperf(uint64_t regnum, uint64_t *val);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NIAGARA2REGS_H */
diff --git a/usr/src/uts/sun4v/sys/niagaraasi.h b/usr/src/uts/sun4v/sys/niagaraasi.h
index 57f0b177c2..584321fe77 100644
--- a/usr/src/uts/sun4v/sys/niagaraasi.h
+++ b/usr/src/uts/sun4v/sys/niagaraasi.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,16 +40,16 @@
extern "C" {
#endif
-#if defined(NIAGARA_IMPL)
+#if defined(NIAGARA_IMPL) || defined(NIAGARA2_IMPL)
/*
- * NIAGARA specific ASIs
+ * NIAGARA and NIAGARA2 specific ASIs
*/
#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* block as if user secondary */
#define ASI_BLK_INIT_ST_QUAD_LDD_P 0xE2 /* block initializing primary */
#else
-#error "This file has ASIs which are specific to Niagara CPU"
+#error "This file has ASIs which are specific to Niagara and Niagara2 CPUs"
#endif /* NIAGARA_IMPL */
#ifdef __cplusplus
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge.h b/usr/src/uts/sun4v/sys/nxge/nxge.h
new file mode 100644
index 0000000000..3940843478
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge.h
@@ -0,0 +1,1154 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_H
+#define _SYS_NXGE_NXGE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_KERNEL) || defined(COSIM)
+#include <nxge_mac.h>
+#include <nxge_ipp.h>
+#include <nxge_fflp.h>
+#endif
+
+/*
+ * NXGE diagnostics IOCTLS.
+ */
+#define NXGE_IOC ((((('N' << 8) + 'X') << 8) + 'G') << 8)
+
+#define NXGE_GET64 (NXGE_IOC|1)
+#define NXGE_PUT64 (NXGE_IOC|2)
+#define NXGE_GET_TX_RING_SZ (NXGE_IOC|3)
+#define NXGE_GET_TX_DESC (NXGE_IOC|4)
+#define NXGE_GLOBAL_RESET (NXGE_IOC|5)
+#define NXGE_TX_SIDE_RESET (NXGE_IOC|6)
+#define NXGE_RX_SIDE_RESET (NXGE_IOC|7)
+#define NXGE_RESET_MAC (NXGE_IOC|8)
+
+#define NXGE_GET_MII (NXGE_IOC|11)
+#define NXGE_PUT_MII (NXGE_IOC|12)
+#define NXGE_RTRACE (NXGE_IOC|13)
+#define NXGE_RTRACE_TEST (NXGE_IOC|20)
+#define NXGE_TX_REGS_DUMP (NXGE_IOC|21)
+#define NXGE_RX_REGS_DUMP (NXGE_IOC|22)
+#define NXGE_INT_REGS_DUMP (NXGE_IOC|23)
+#define NXGE_VIR_REGS_DUMP (NXGE_IOC|24)
+#define NXGE_VIR_INT_REGS_DUMP (NXGE_IOC|25)
+#define NXGE_RDUMP (NXGE_IOC|26)
+#define NXGE_RDC_GRPS_DUMP (NXGE_IOC|27)
+#define NXGE_PIO_TEST (NXGE_IOC|28)
+
+#define NXGE_GET_TCAM (NXGE_IOC|29)
+#define NXGE_PUT_TCAM (NXGE_IOC|30)
+#define NXGE_INJECT_ERR (NXGE_IOC|40)
+
+#if (defined(SOLARIS) && defined(_KERNEL)) || defined(COSIM)
+#define NXGE_OK 0
+#define NXGE_ERROR 0x40000000
+#define NXGE_DDI_FAILED 0x20000000
+#define NXGE_GET_PORT_NUM(n) n
+
+/*
+ * Definitions for module_info.
+ */
+#define NXGE_IDNUM (0) /* module ID number */
+#ifdef SAM_MODEL
+#define NXGE_DRIVER_NAME "ce" /* module name */
+#else
+#define NXGE_DRIVER_NAME "nxge" /* module name */
+#endif
+
+#define NXGE_MINPSZ (0) /* min packet size */
+#define NXGE_MAXPSZ (ETHERMTU) /* max packet size */
+#define NXGE_HIWAT (2048 * NXGE_MAXPSZ) /* hi-water mark */
+#define NXGE_LOWAT (1) /* lo-water mark */
+#define NXGE_HIWAT_MAX (192000 * NXGE_MAXPSZ)
+#define NXGE_HIWAT_MIN (2 * NXGE_MAXPSZ)
+#define NXGE_LOWAT_MAX (192000 * NXGE_MAXPSZ)
+#define NXGE_LOWAT_MIN (1)
+
+#ifndef D_HOTPLUG
+#define D_HOTPLUG 0x00
+#endif
+
+#define INIT_BUCKET_SIZE 16 /* Initial Hash Bucket Size */
+
+#define NXGE_CHECK_TIMER (5000)
+
+typedef enum {
+ param_instance,
+ param_main_instance,
+ param_function_number,
+ param_partition_id,
+ param_read_write_mode,
+ param_niu_cfg_type,
+ param_tx_quick_cfg,
+ param_rx_quick_cfg,
+ param_master_cfg_enable,
+ param_master_cfg_value,
+
+ param_autoneg,
+ param_anar_10gfdx,
+ param_anar_10ghdx,
+ param_anar_1000fdx,
+ param_anar_1000hdx,
+ param_anar_100T4,
+ param_anar_100fdx,
+ param_anar_100hdx,
+ param_anar_10fdx,
+ param_anar_10hdx,
+
+ param_anar_asmpause,
+ param_anar_pause,
+ param_use_int_xcvr,
+ param_enable_ipg0,
+ param_ipg0,
+ param_ipg1,
+ param_ipg2,
+ param_accept_jumbo,
+ param_txdma_weight,
+ param_txdma_channels_begin,
+
+ param_txdma_channels,
+ param_txdma_info,
+ param_rxdma_channels_begin,
+ param_rxdma_channels,
+ param_rxdma_drr_weight,
+ param_rxdma_full_header,
+ param_rxdma_info,
+ param_rxdma_rbr_size,
+ param_rxdma_rcr_size,
+ param_default_port_rdc,
+ param_rxdma_intr_time,
+ param_rxdma_intr_pkts,
+
+ param_rdc_grps_start,
+ param_rx_rdc_grps,
+ param_default_grp0_rdc,
+ param_default_grp1_rdc,
+ param_default_grp2_rdc,
+ param_default_grp3_rdc,
+ param_default_grp4_rdc,
+ param_default_grp5_rdc,
+ param_default_grp6_rdc,
+ param_default_grp7_rdc,
+
+ param_info_rdc_groups,
+ param_start_ldg,
+ param_max_ldg,
+ param_mac_2rdc_grp,
+ param_vlan_2rdc_grp,
+ param_fcram_part_cfg,
+ param_fcram_access_ratio,
+ param_tcam_access_ratio,
+ param_tcam_enable,
+ param_hash_lookup_enable,
+ param_llc_snap_enable,
+
+ param_h1_init_value,
+ param_h2_init_value,
+ param_class_cfg_ether_usr1,
+ param_class_cfg_ether_usr2,
+ param_class_cfg_ip_usr4,
+ param_class_cfg_ip_usr5,
+ param_class_cfg_ip_usr6,
+ param_class_cfg_ip_usr7,
+ param_class_opt_ip_usr4,
+ param_class_opt_ip_usr5,
+ param_class_opt_ip_usr6,
+ param_class_opt_ip_usr7,
+ param_class_opt_ipv4_tcp,
+ param_class_opt_ipv4_udp,
+ param_class_opt_ipv4_ah,
+ param_class_opt_ipv4_sctp,
+ param_class_opt_ipv6_tcp,
+ param_class_opt_ipv6_udp,
+ param_class_opt_ipv6_ah,
+ param_class_opt_ipv6_sctp,
+ param_nxge_debug_flag,
+ param_npi_debug_flag,
+ param_dump_rdc,
+ param_dump_tdc,
+ param_dump_mac_regs,
+ param_dump_ipp_regs,
+ param_dump_fflp_regs,
+ param_dump_vlan_table,
+ param_dump_rdc_table,
+ param_dump_ptrs,
+ param_end
+} nxge_param_index_t;
+
+
+/*
+ * Named Dispatch Parameter Management Structure
+ */
+
+
+typedef int (*nxge_ndgetf_t)(p_nxge_t, queue_t *, MBLKP, caddr_t, cred_t *);
+typedef int (*nxge_ndsetf_t)(p_nxge_t, queue_t *,
+ MBLKP, char *, caddr_t, cred_t *);
+
+#define NXGE_PARAM_READ 0x00000001ULL
+#define NXGE_PARAM_WRITE 0x00000002ULL
+#define NXGE_PARAM_SHARED 0x00000004ULL
+#define NXGE_PARAM_PRIV 0x00000008ULL
+#define NXGE_PARAM_RW NXGE_PARAM_READ | NXGE_PARAM_WRITE
+#define NXGE_PARAM_RWS NXGE_PARAM_RW | NXGE_PARAM_SHARED
+#define NXGE_PARAM_RWP NXGE_PARAM_RW | NXGE_PARAM_PRIV
+
+#define NXGE_PARAM_RXDMA 0x00000010ULL
+#define NXGE_PARAM_TXDMA 0x00000020ULL
+#define NXGE_PARAM_CLASS_GEN 0x00000040ULL
+#define NXGE_PARAM_MAC 0x00000080ULL
+#define NXGE_PARAM_CLASS_BIN NXGE_PARAM_CLASS_GEN | NXGE_PARAM_BASE_BIN
+#define NXGE_PARAM_CLASS_HEX NXGE_PARAM_CLASS_GEN | NXGE_PARAM_BASE_HEX
+#define NXGE_PARAM_CLASS NXGE_PARAM_CLASS_HEX
+
+#define NXGE_PARAM_CMPLX 0x00010000ULL
+#define NXGE_PARAM_NDD_WR_OK 0x00020000ULL
+#define NXGE_PARAM_INIT_ONLY 0x00040000ULL
+#define NXGE_PARAM_INIT_CONFIG 0x00080000ULL
+
+#define NXGE_PARAM_READ_PROP 0x00100000ULL
+#define NXGE_PARAM_PROP_ARR32 0x00200000ULL
+#define NXGE_PARAM_PROP_ARR64 0x00400000ULL
+#define NXGE_PARAM_PROP_STR 0x00800000ULL
+
+#define NXGE_PARAM_BASE_DEC 0x00000000ULL
+#define NXGE_PARAM_BASE_BIN 0x10000000ULL
+#define NXGE_PARAM_BASE_HEX 0x20000000ULL
+#define NXGE_PARAM_BASE_STR 0x40000000ULL
+#define NXGE_PARAM_DONT_SHOW 0x80000000ULL
+
+#define NXGE_PARAM_ARRAY_CNT_MASK 0x0000ffff00000000ULL
+#define NXGE_PARAM_ARRAY_CNT_SHIFT 32ULL
+#define NXGE_PARAM_ARRAY_ALLOC_MASK 0xffff000000000000ULL
+#define NXGE_PARAM_ARRAY_ALLOC_SHIFT 48ULL
+
+typedef struct _nxge_param_t {
+ int (*getf)();
+ int (*setf)(); /* null for read only */
+ uint64_t type; /* R/W/ Common/Port/ .... */
+ uint64_t minimum;
+ uint64_t maximum;
+ uint64_t value; /* for array params, pointer to value array */
+ uint64_t old_value; /* for array params, pointer to old_value array */
+ char *fcode_name;
+ char *name;
+} nxge_param_t, *p_nxge_param_t;
+
+
+
+typedef enum {
+ nxge_lb_normal,
+ nxge_lb_ext10g,
+ nxge_lb_ext1000,
+ nxge_lb_ext100,
+ nxge_lb_ext10,
+ nxge_lb_phy10g,
+ nxge_lb_phy1000,
+ nxge_lb_phy,
+ nxge_lb_serdes10g,
+ nxge_lb_serdes1000,
+ nxge_lb_serdes,
+ nxge_lb_mac10g,
+ nxge_lb_mac1000,
+ nxge_lb_mac
+} nxge_lb_t;
+
+enum nxge_mac_state {
+ NXGE_MAC_STOPPED = 0,
+ NXGE_MAC_STARTED
+};
+
+/*
+ * Private DLPI full dlsap address format.
+ */
+typedef struct _nxge_dladdr_t {
+ ether_addr_st dl_phys;
+ uint16_t dl_sap;
+} nxge_dladdr_t, *p_nxge_dladdr_t;
+
+typedef struct _mc_addr_t {
+ ether_addr_st multcast_addr;
+ uint_t mc_addr_cnt;
+} mc_addr_t, *p_mc_addr_t;
+
+typedef struct _mc_bucket_t {
+ p_mc_addr_t addr_list;
+ uint_t list_size;
+} mc_bucket_t, *p_mc_bucket_t;
+
+typedef struct _mc_table_t {
+ p_mc_bucket_t bucket_list;
+ uint_t buckets_used;
+} mc_table_t, *p_mc_table_t;
+
+typedef struct _filter_t {
+ uint32_t all_phys_cnt;
+ uint32_t all_multicast_cnt;
+ uint32_t all_sap_cnt;
+} filter_t, *p_filter_t;
+
+#if defined(_KERNEL) || defined(COSIM)
+
+
+typedef struct _nxge_port_stats_t {
+ /*
+ * Overall structure size
+ */
+ size_t stats_size;
+
+ /*
+ * Link Input/Output stats
+ */
+ uint64_t ipackets;
+ uint64_t ierrors;
+ uint64_t opackets;
+ uint64_t oerrors;
+ uint64_t collisions;
+
+ /*
+ * MIB II variables
+ */
+ uint64_t rbytes; /* # bytes received */
+ uint64_t obytes; /* # bytes transmitted */
+ uint32_t multircv; /* # multicast packets received */
+ uint32_t multixmt; /* # multicast packets for xmit */
+ uint32_t brdcstrcv; /* # broadcast packets received */
+ uint32_t brdcstxmt; /* # broadcast packets for xmit */
+ uint32_t norcvbuf; /* # rcv packets discarded */
+ uint32_t noxmtbuf; /* # xmit packets discarded */
+
+ /*
+ * Lets the user know the MTU currently in use by
+ * the physical MAC port.
+ */
+ nxge_lb_t lb_mode;
+ uint32_t qos_mode;
+ uint32_t trunk_mode;
+ uint32_t poll_mode;
+
+ /*
+ * Tx Statistics.
+ */
+ uint32_t tx_inits;
+ uint32_t tx_starts;
+ uint32_t tx_nocanput;
+ uint32_t tx_msgdup_fail;
+ uint32_t tx_allocb_fail;
+ uint32_t tx_no_desc;
+ uint32_t tx_dma_bind_fail;
+ uint32_t tx_uflo;
+ uint32_t tx_hdr_pkts;
+ uint32_t tx_ddi_pkts;
+ uint32_t tx_dvma_pkts;
+
+ uint32_t tx_max_pend;
+
+ /*
+ * Rx Statistics.
+ */
+ uint32_t rx_inits;
+ uint32_t rx_hdr_pkts;
+ uint32_t rx_mtu_pkts;
+ uint32_t rx_split_pkts;
+ uint32_t rx_no_buf;
+ uint32_t rx_no_comp_wb;
+ uint32_t rx_ov_flow;
+ uint32_t rx_len_mm;
+ uint32_t rx_tag_err;
+ uint32_t rx_nocanput;
+ uint32_t rx_msgdup_fail;
+ uint32_t rx_allocb_fail;
+
+ /*
+ * Receive buffer management statistics.
+ */
+ uint32_t rx_new_pages;
+ uint32_t rx_new_hdr_pgs;
+ uint32_t rx_new_mtu_pgs;
+ uint32_t rx_new_nxt_pgs;
+ uint32_t rx_reused_pgs;
+ uint32_t rx_hdr_drops;
+ uint32_t rx_mtu_drops;
+ uint32_t rx_nxt_drops;
+
+ /*
+ * Receive flow statistics
+ */
+ uint32_t rx_rel_flow;
+ uint32_t rx_rel_bit;
+
+ uint32_t rx_pkts_dropped;
+
+ /*
+ * PCI-E Bus Statistics.
+ */
+ uint32_t pci_bus_speed;
+ uint32_t pci_err;
+ uint32_t pci_rta_err;
+ uint32_t pci_rma_err;
+ uint32_t pci_parity_err;
+ uint32_t pci_bad_ack_err;
+ uint32_t pci_drto_err;
+ uint32_t pci_dmawz_err;
+ uint32_t pci_dmarz_err;
+
+ uint32_t rx_taskq_waits;
+
+ uint32_t tx_jumbo_pkts;
+
+ /*
+ * Some statistics added to support bringup, these
+ * should be removed.
+ */
+ uint32_t user_defined;
+} nxge_port_stats_t, *p_nxge_port_stats_t;
+
+
+typedef struct _nxge_stats_t {
+ /*
+ * Overall structure size
+ */
+ size_t stats_size;
+
+ kstat_t *ksp;
+ kstat_t *rdc_ksp[NXGE_MAX_RDCS];
+ kstat_t *tdc_ksp[NXGE_MAX_TDCS];
+ kstat_t *rdc_sys_ksp;
+ kstat_t *fflp_ksp[1];
+ kstat_t *ipp_ksp;
+ kstat_t *txc_ksp;
+ kstat_t *mac_ksp;
+ kstat_t *zcp_ksp;
+ kstat_t *port_ksp;
+ kstat_t *mmac_ksp;
+
+ nxge_mac_stats_t mac_stats; /* Common MAC Statistics */
+ nxge_xmac_stats_t xmac_stats; /* XMAC Statistics */
+ nxge_bmac_stats_t bmac_stats; /* BMAC Statistics */
+
+ nxge_rx_ring_stats_t rx_stats; /* per port RX stats */
+ nxge_ipp_stats_t ipp_stats; /* per port IPP stats */
+ nxge_zcp_stats_t zcp_stats; /* per port IPP stats */
+ nxge_rx_ring_stats_t rdc_stats[NXGE_MAX_RDCS]; /* per rdc stats */
+ nxge_rdc_sys_stats_t rdc_sys_stats; /* per port RDC stats */
+
+ nxge_tx_ring_stats_t tx_stats; /* per port TX stats */
+ nxge_txc_stats_t txc_stats; /* per port TX stats */
+ nxge_tx_ring_stats_t tdc_stats[NXGE_MAX_TDCS]; /* per tdc stats */
+ nxge_fflp_stats_t fflp_stats; /* fflp stats */
+ nxge_port_stats_t port_stats; /* fflp stats */
+ nxge_mmac_stats_t mmac_stats; /* Multi mac. stats */
+
+} nxge_stats_t, *p_nxge_stats_t;
+
+
+
+typedef struct _nxge_intr_t {
+ boolean_t intr_registered; /* interrupts are registered */
+ boolean_t intr_enabled; /* interrupts are enabled */
+ boolean_t niu_msi_enable; /* debug or configurable? */
+ uint8_t nldevs; /* # of logical devices */
+ int intr_types; /* interrupt types supported */
+ int intr_type; /* interrupt type to add */
+ int max_int_cnt; /* max MSIX/INT HW supports */
+ int start_inum; /* start inum (in sequence?) */
+ int msi_intx_cnt; /* # msi/intx ints returned */
+ int intr_added; /* # ints actually needed */
+ int intr_cap; /* interrupt capabilities */
+ size_t intr_size; /* size of array to allocate */
+ ddi_intr_handle_t *htable; /* For array of interrupts */
+ /* Add interrupt number for each interrupt vector */
+ int pri;
+} nxge_intr_t, *p_nxge_intr_t;
+
+typedef struct _nxge_ldgv_t {
+ uint8_t ndma_ldvs;
+ uint8_t nldvs;
+ uint8_t start_ldg;
+ uint8_t start_ldg_tx;
+ uint8_t start_ldg_rx;
+ uint8_t maxldgs;
+ uint8_t maxldvs;
+ uint8_t ldg_intrs;
+ boolean_t own_sys_err;
+ boolean_t own_max_ldv;
+ uint32_t tmres;
+ p_nxge_ldg_t ldgp;
+ p_nxge_ldv_t ldvp;
+ p_nxge_ldv_t ldvp_syserr;
+} nxge_ldgv_t, *p_nxge_ldgv_t;
+
+/*
+ * Neptune Device instance state information.
+ *
+ * Each instance is dynamically allocated on first attach.
+ */
+struct _nxge_t {
+ dev_info_t *dip; /* device instance */
+ dev_info_t *p_dip; /* Parent's device instance */
+ int instance; /* instance number */
+ int function_num; /* device function number */
+ int nports; /* # of ports on this device */
+ int board_ver; /* Board Version */
+ int partition_id; /* partition ID */
+ int use_partition; /* partition is enabled */
+ uint32_t drv_state; /* driver state bit flags */
+ uint64_t nxge_debug_level; /* driver state bit flags */
+ kmutex_t genlock[1];
+ enum nxge_mac_state nxge_mac_state;
+ ddi_softintr_t resched_id; /* reschedule callback */
+ boolean_t resched_needed;
+ boolean_t resched_running;
+
+ p_dev_regs_t dev_regs;
+ npi_handle_t npi_handle;
+ npi_handle_t npi_pci_handle;
+ npi_handle_t npi_reg_handle;
+ npi_handle_t npi_msi_handle;
+ npi_handle_t npi_vreg_handle;
+ npi_handle_t npi_v2reg_handle;
+
+ nxge_mac_t mac;
+ nxge_ipp_t ipp;
+ nxge_txc_t txc;
+ nxge_classify_t classifier;
+
+ mac_handle_t mach; /* mac module handle */
+ p_nxge_stats_t statsp;
+ uint32_t param_count;
+ p_nxge_param_t param_arr;
+ nxge_hw_list_t *nxge_hw_p; /* pointer to per Neptune */
+ niu_type_t niu_type;
+ boolean_t os_addr_mode32; /* set to 1 for 32 bit mode */
+ uint8_t nrdc;
+ uint8_t def_rdc;
+ uint8_t rdc[NXGE_MAX_RDCS];
+ uint8_t ntdc;
+ uint8_t tdc[NXGE_MAX_TDCS];
+
+ nxge_intr_t nxge_intr_type;
+ nxge_dma_pt_cfg_t pt_config;
+ nxge_class_pt_cfg_t class_config;
+
+ /* Logical device and group data structures. */
+ p_nxge_ldgv_t ldgvp;
+
+ caddr_t param_list; /* Parameter list */
+
+ ether_addr_st factaddr; /* factory mac address */
+ ether_addr_st ouraddr; /* individual address */
+ kmutex_t ouraddr_lock; /* lock to protect to uradd */
+
+ ddi_iblock_cookie_t interrupt_cookie;
+
+ /*
+ * Blocks of memory may be pre-allocated by the
+ * partition manager or the driver. They may include
+ * blocks for configuration and buffers. The idea is
+ * to preallocate big blocks of contiguous areas in
+ * system memory (i.e. with IOMMU). These blocks then
+ * will be broken up to a fixed number of blocks with
+ * each block having the same block size (4K, 8K, 16K or
+ * 32K) in the case of buffer blocks. For systems that
+ * do not support DVMA, more than one big block will be
+ * allocated.
+ */
+ uint32_t rx_default_block_size;
+ nxge_rx_block_size_t rx_bksize_code;
+
+ p_nxge_dma_pool_t rx_buf_pool_p;
+ p_nxge_dma_pool_t rx_cntl_pool_p;
+
+ p_nxge_dma_pool_t tx_buf_pool_p;
+ p_nxge_dma_pool_t tx_cntl_pool_p;
+
+ /* Receive buffer block ring and completion ring. */
+ p_rx_rbr_rings_t rx_rbr_rings;
+ p_rx_rcr_rings_t rx_rcr_rings;
+ p_rx_mbox_areas_t rx_mbox_areas_p;
+
+ p_rx_tx_params_t rx_params;
+ uint32_t start_rdc;
+ uint32_t max_rdcs;
+ uint32_t rdc_mask;
+
+ /* Transmit descriptors rings */
+ p_tx_rings_t tx_rings;
+ p_tx_mbox_areas_t tx_mbox_areas_p;
+
+ uint32_t start_tdc;
+ uint32_t max_tdcs;
+ uint32_t tdc_mask;
+
+ p_rx_tx_params_t tx_params;
+
+ ddi_dma_handle_t dmasparehandle;
+
+ ulong_t sys_page_sz;
+ ulong_t sys_page_mask;
+ int suspended;
+
+ mii_bmsr_t bmsr; /* xcvr status at last poll. */
+ mii_bmsr_t soft_bmsr; /* xcvr status kept by SW. */
+
+ kmutex_t mif_lock; /* Lock to protect the list. */
+
+ void (*mii_read)();
+ void (*mii_write)();
+ void (*mii_poll)();
+ filter_t filter; /* Current instance filter */
+ p_hash_filter_t hash_filter; /* Multicast hash filter. */
+ krwlock_t filter_lock; /* Lock to protect filters. */
+
+ ulong_t sys_burst_sz;
+
+ uint8_t cache_line;
+
+ timeout_id_t nxge_link_poll_timerid;
+ timeout_id_t nxge_timerid;
+
+ uint_t need_periodic_reclaim;
+ timeout_id_t reclaim_timer;
+
+ uint8_t msg_min;
+ uint8_t crc_size;
+
+ boolean_t hard_props_read;
+
+ boolean_t nxge_htraffic;
+ uint32_t nxge_ncpus;
+ uint32_t nxge_cpumask;
+ uint32_t nxge_intrpkt;
+ uchar_t nxge_rxmode;
+ uint32_t active_threads;
+
+ rtrace_t rtrace;
+ int fm_capabilities; /* FMA capabilities */
+
+ uint32_t nxge_port_rbr_size;
+ uint32_t nxge_port_rcr_size;
+ uint32_t nxge_port_tx_ring_size;
+ nxge_mmac_t nxge_mmac_info;
+#if defined(sun4v)
+ boolean_t niu_hsvc_available;
+ hsvc_info_t niu_hsvc;
+ uint64_t niu_min_ver;
+#endif
+};
+
+/*
+ * Driver state flags.
+ */
+#define STATE_REGS_MAPPED 0x000000001 /* device registers mapped */
+#define STATE_KSTATS_SETUP 0x000000002 /* kstats allocated */
+#define STATE_NODE_CREATED 0x000000004 /* device node created */
+#define STATE_HW_CONFIG_CREATED 0x000000008 /* hardware properties */
+#define STATE_HW_INITIALIZED 0x000000010 /* hardware initialized */
+#define STATE_MDIO_LOCK_INIT 0x000000020 /* mdio lock initialized */
+#define STATE_MII_LOCK_INIT 0x000000040 /* mii lock initialized */
+
+#define STOP_POLL_THRESH 9
+#define START_POLL_THRESH 2
+
+typedef struct _nxge_port_kstat_t {
+ /*
+ * Link Input/Output stats
+ */
+ kstat_named_t ipackets;
+ kstat_named_t ipackets64;
+ kstat_named_t ierrors;
+ kstat_named_t opackets;
+ kstat_named_t opackets64;
+ kstat_named_t oerrors;
+ kstat_named_t collisions;
+
+ /*
+ * required by kstat for MIB II objects(RFC 1213)
+ */
+ kstat_named_t rbytes; /* # octets received */
+ /* MIB - ifInOctets */
+ kstat_named_t rbytes64;
+ kstat_named_t obytes; /* # octets transmitted */
+ /* MIB - ifOutOctets */
+ kstat_named_t obytes64;
+ kstat_named_t multircv; /* # multicast packets */
+ /* delivered to upper layer */
+ /* MIB - ifInNUcastPkts */
+ kstat_named_t multixmt; /* # multicast packets */
+ /* requested to be sent */
+ /* MIB - ifOutNUcastPkts */
+ kstat_named_t brdcstrcv; /* # broadcast packets */
+ /* delivered to upper layer */
+ /* MIB - ifInNUcastPkts */
+ kstat_named_t brdcstxmt; /* # broadcast packets */
+ /* requested to be sent */
+ /* MIB - ifOutNUcastPkts */
+ kstat_named_t norcvbuf; /* # rcv packets discarded */
+ /* MIB - ifInDiscards */
+ kstat_named_t noxmtbuf; /* # xmt packets discarded */
+ /* MIB - ifOutDiscards */
+
+ /*
+ * Transciever state informations.
+ */
+ kstat_named_t xcvr_inits;
+ kstat_named_t xcvr_inuse;
+ kstat_named_t xcvr_addr;
+ kstat_named_t xcvr_id;
+ kstat_named_t cap_autoneg;
+ kstat_named_t cap_10gfdx;
+ kstat_named_t cap_10ghdx;
+ kstat_named_t cap_1000fdx;
+ kstat_named_t cap_1000hdx;
+ kstat_named_t cap_100T4;
+ kstat_named_t cap_100fdx;
+ kstat_named_t cap_100hdx;
+ kstat_named_t cap_10fdx;
+ kstat_named_t cap_10hdx;
+ kstat_named_t cap_asmpause;
+ kstat_named_t cap_pause;
+
+ /*
+ * Link partner capabilities.
+ */
+ kstat_named_t lp_cap_autoneg;
+ kstat_named_t lp_cap_10gfdx;
+ kstat_named_t lp_cap_10ghdx;
+ kstat_named_t lp_cap_1000fdx;
+ kstat_named_t lp_cap_1000hdx;
+ kstat_named_t lp_cap_100T4;
+ kstat_named_t lp_cap_100fdx;
+ kstat_named_t lp_cap_100hdx;
+ kstat_named_t lp_cap_10fdx;
+ kstat_named_t lp_cap_10hdx;
+ kstat_named_t lp_cap_asmpause;
+ kstat_named_t lp_cap_pause;
+
+ /*
+ * Shared link setup.
+ */
+ kstat_named_t link_T4;
+ kstat_named_t link_speed;
+ kstat_named_t link_duplex;
+ kstat_named_t link_asmpause;
+ kstat_named_t link_pause;
+ kstat_named_t link_up;
+
+ /*
+ * Lets the user know the MTU currently in use by
+ * the physical MAC port.
+ */
+ kstat_named_t mac_mtu;
+ kstat_named_t lb_mode;
+ kstat_named_t qos_mode;
+ kstat_named_t trunk_mode;
+
+ /*
+ * Tx Statistics.
+ */
+ kstat_named_t tx_inits;
+ kstat_named_t tx_starts;
+ kstat_named_t tx_nocanput;
+ kstat_named_t tx_msgdup_fail;
+ kstat_named_t tx_allocb_fail;
+ kstat_named_t tx_no_desc;
+ kstat_named_t tx_dma_bind_fail;
+ kstat_named_t tx_uflo;
+ kstat_named_t tx_hdr_pkts;
+ kstat_named_t tx_ddi_pkts;
+ kstat_named_t tx_dvma_pkts;
+
+ kstat_named_t tx_max_pend;
+
+ /*
+ * Rx Statistics.
+ */
+ kstat_named_t rx_inits;
+ kstat_named_t rx_hdr_pkts;
+ kstat_named_t rx_mtu_pkts;
+ kstat_named_t rx_split_pkts;
+ kstat_named_t rx_no_buf;
+ kstat_named_t rx_no_comp_wb;
+ kstat_named_t rx_ov_flow;
+ kstat_named_t rx_len_mm;
+ kstat_named_t rx_tag_err;
+ kstat_named_t rx_nocanput;
+ kstat_named_t rx_msgdup_fail;
+ kstat_named_t rx_allocb_fail;
+
+ /*
+ * Receive buffer management statistics.
+ */
+ kstat_named_t rx_new_pages;
+ kstat_named_t rx_new_hdr_pgs;
+ kstat_named_t rx_new_mtu_pgs;
+ kstat_named_t rx_new_nxt_pgs;
+ kstat_named_t rx_reused_pgs;
+ kstat_named_t rx_hdr_drops;
+ kstat_named_t rx_mtu_drops;
+ kstat_named_t rx_nxt_drops;
+
+ /*
+ * Receive flow statistics
+ */
+ kstat_named_t rx_rel_flow;
+ kstat_named_t rx_rel_bit;
+ kstat_named_t rx_pkts_dropped;
+
+ /*
+ * Misc MAC statistics.
+ */
+ kstat_named_t ifspeed;
+ kstat_named_t promisc;
+ kstat_named_t rev_id;
+
+ /* Global (entire NIU/Neptune device) statistics */
+
+ /*
+ * PCI Bus Statistics.
+ */
+ kstat_named_t pci_bus_speed;
+ kstat_named_t pci_err;
+ kstat_named_t pci_rta_err;
+ kstat_named_t pci_rma_err;
+ kstat_named_t pci_parity_err;
+ kstat_named_t pci_bad_ack_err;
+ kstat_named_t pci_drto_err;
+ kstat_named_t pci_dmawz_err;
+ kstat_named_t pci_dmarz_err;
+
+ kstat_named_t rx_taskq_waits;
+
+ /*
+ * Some statistics added to support bringup, these
+ * should be removed.
+ */
+ kstat_named_t user_defined;
+} nxge_port_kstat_t, *p_nxge_port_kstat_t;
+
+typedef struct _nxge_rdc_kstat {
+ /*
+ * Receive DMA channel statistics.
+ */
+ kstat_named_t ipackets;
+ kstat_named_t rbytes;
+ kstat_named_t errors;
+ kstat_named_t dcf_err;
+ kstat_named_t rcr_ack_err;
+
+ kstat_named_t dc_fifoflow_err;
+ kstat_named_t rcr_sha_par_err;
+ kstat_named_t rbr_pre_par_err;
+ kstat_named_t wred_drop;
+ kstat_named_t rbr_pre_emty;
+
+ kstat_named_t rcr_shadow_full;
+ kstat_named_t rbr_tmout;
+ kstat_named_t rsp_cnt_err;
+ kstat_named_t byte_en_bus;
+ kstat_named_t rsp_dat_err;
+
+ kstat_named_t compl_l2_err;
+ kstat_named_t compl_l4_cksum_err;
+ kstat_named_t compl_zcp_soft_err;
+ kstat_named_t compl_fflp_soft_err;
+ kstat_named_t config_err;
+
+ kstat_named_t rcrincon;
+ kstat_named_t rcrfull;
+ kstat_named_t rbr_empty;
+ kstat_named_t rbrfull;
+ kstat_named_t rbrlogpage;
+
+ kstat_named_t cfiglogpage;
+ kstat_named_t port_drop_pkt;
+ kstat_named_t rcr_to;
+ kstat_named_t rcr_thresh;
+ kstat_named_t rcr_mex;
+ kstat_named_t id_mismatch;
+ kstat_named_t zcp_eop_err;
+ kstat_named_t ipp_eop_err;
+} nxge_rdc_kstat_t, *p_nxge_rdc_kstat_t;
+
+typedef struct _nxge_rdc_sys_kstat {
+ /*
+ * Receive DMA system statistics.
+ */
+ kstat_named_t pre_par;
+ kstat_named_t sha_par;
+ kstat_named_t id_mismatch;
+ kstat_named_t ipp_eop_err;
+ kstat_named_t zcp_eop_err;
+} nxge_rdc_sys_kstat_t, *p_nxge_rdc_sys_kstat_t;
+
+typedef struct _nxge_tdc_kstat {
+ /*
+ * Transmit DMA channel statistics.
+ */
+ kstat_named_t opackets;
+ kstat_named_t obytes;
+ kstat_named_t oerrors;
+ kstat_named_t tx_inits;
+ kstat_named_t tx_no_buf;
+
+ kstat_named_t mbox_err;
+ kstat_named_t pkt_size_err;
+ kstat_named_t tx_ring_oflow;
+ kstat_named_t pref_buf_ecc_err;
+ kstat_named_t nack_pref;
+ kstat_named_t nack_pkt_rd;
+ kstat_named_t conf_part_err;
+ kstat_named_t pkt_prt_err;
+ kstat_named_t reset_fail;
+/* used to in the common (per port) counter */
+
+ kstat_named_t tx_starts;
+ kstat_named_t tx_nocanput;
+ kstat_named_t tx_msgdup_fail;
+ kstat_named_t tx_allocb_fail;
+ kstat_named_t tx_no_desc;
+ kstat_named_t tx_dma_bind_fail;
+ kstat_named_t tx_uflo;
+ kstat_named_t tx_hdr_pkts;
+ kstat_named_t tx_ddi_pkts;
+ kstat_named_t tx_dvma_pkts;
+ kstat_named_t tx_max_pend;
+} nxge_tdc_kstat_t, *p_nxge_tdc_kstat_t;
+
+typedef struct _nxge_txc_kstat {
+ /*
+ * Transmit port TXC block statistics.
+ */
+ kstat_named_t pkt_stuffed;
+ kstat_named_t pkt_xmit;
+ kstat_named_t ro_correct_err;
+ kstat_named_t ro_uncorrect_err;
+ kstat_named_t sf_correct_err;
+ kstat_named_t sf_uncorrect_err;
+ kstat_named_t address_failed;
+ kstat_named_t dma_failed;
+ kstat_named_t length_failed;
+ kstat_named_t pkt_assy_dead;
+ kstat_named_t reorder_err;
+} nxge_txc_kstat_t, *p_nxge_txc_kstat_t;
+
+typedef struct _nxge_ipp_kstat {
+ /*
+ * Receive port IPP block statistics.
+ */
+ kstat_named_t eop_miss;
+ kstat_named_t sop_miss;
+ kstat_named_t dfifo_ue;
+ kstat_named_t ecc_err_cnt;
+ kstat_named_t dfifo_perr;
+ kstat_named_t pfifo_over;
+ kstat_named_t pfifo_und;
+ kstat_named_t bad_cs_cnt;
+ kstat_named_t pkt_dis_cnt;
+ kstat_named_t cs_fail;
+} nxge_ipp_kstat_t, *p_nxge_ipp_kstat_t;
+
+typedef struct _nxge_zcp_kstat {
+ /*
+ * ZCP statistics.
+ */
+ kstat_named_t errors;
+ kstat_named_t inits;
+ kstat_named_t rrfifo_underrun;
+ kstat_named_t rrfifo_overrun;
+ kstat_named_t rspfifo_uncorr_err;
+ kstat_named_t buffer_overflow;
+ kstat_named_t stat_tbl_perr;
+ kstat_named_t dyn_tbl_perr;
+ kstat_named_t buf_tbl_perr;
+ kstat_named_t tt_program_err;
+ kstat_named_t rsp_tt_index_err;
+ kstat_named_t slv_tt_index_err;
+ kstat_named_t zcp_tt_index_err;
+ kstat_named_t access_fail;
+ kstat_named_t cfifo_ecc;
+} nxge_zcp_kstat_t, *p_nxge_zcp_kstat_t;
+
+typedef struct _nxge_mac_kstat {
+ /*
+ * Transmit MAC statistics.
+ */
+ kstat_named_t tx_frame_cnt;
+ kstat_named_t tx_underflow_err;
+ kstat_named_t tx_overflow_err;
+ kstat_named_t tx_maxpktsize_err;
+ kstat_named_t tx_fifo_xfr_err;
+ kstat_named_t tx_byte_cnt;
+
+ /*
+ * Receive MAC statistics.
+ */
+ kstat_named_t rx_frame_cnt;
+ kstat_named_t rx_underflow_err;
+ kstat_named_t rx_overflow_err;
+ kstat_named_t rx_len_err_cnt;
+ kstat_named_t rx_crc_err_cnt;
+ kstat_named_t rx_viol_err_cnt;
+ kstat_named_t rx_byte_cnt;
+ kstat_named_t rx_hist1_cnt;
+ kstat_named_t rx_hist2_cnt;
+ kstat_named_t rx_hist3_cnt;
+ kstat_named_t rx_hist4_cnt;
+ kstat_named_t rx_hist5_cnt;
+ kstat_named_t rx_hist6_cnt;
+ kstat_named_t rx_broadcast_cnt;
+ kstat_named_t rx_mult_cnt;
+ kstat_named_t rx_frag_cnt;
+ kstat_named_t rx_frame_align_err_cnt;
+ kstat_named_t rx_linkfault_err_cnt;
+ kstat_named_t rx_local_fault_err_cnt;
+ kstat_named_t rx_remote_fault_err_cnt;
+} nxge_mac_kstat_t, *p_nxge_mac_kstat_t;
+
+typedef struct _nxge_xmac_kstat {
+ /*
+ * XMAC statistics.
+ */
+ kstat_named_t tx_frame_cnt;
+ kstat_named_t tx_underflow_err;
+ kstat_named_t tx_maxpktsize_err;
+ kstat_named_t tx_overflow_err;
+ kstat_named_t tx_fifo_xfr_err;
+ kstat_named_t tx_byte_cnt;
+ kstat_named_t rx_frame_cnt;
+ kstat_named_t rx_underflow_err;
+ kstat_named_t rx_overflow_err;
+ kstat_named_t rx_crc_err_cnt;
+ kstat_named_t rx_len_err_cnt;
+ kstat_named_t rx_viol_err_cnt;
+ kstat_named_t rx_byte_cnt;
+ kstat_named_t rx_hist1_cnt;
+ kstat_named_t rx_hist2_cnt;
+ kstat_named_t rx_hist3_cnt;
+ kstat_named_t rx_hist4_cnt;
+ kstat_named_t rx_hist5_cnt;
+ kstat_named_t rx_hist6_cnt;
+ kstat_named_t rx_hist7_cnt;
+ kstat_named_t rx_broadcast_cnt;
+ kstat_named_t rx_mult_cnt;
+ kstat_named_t rx_frag_cnt;
+ kstat_named_t rx_frame_align_err_cnt;
+ kstat_named_t rx_linkfault_err_cnt;
+ kstat_named_t rx_remote_fault_err_cnt;
+ kstat_named_t rx_local_fault_err_cnt;
+ kstat_named_t rx_pause_cnt;
+ kstat_named_t xpcs_deskew_err_cnt;
+ kstat_named_t xpcs_ln0_symbol_err_cnt;
+ kstat_named_t xpcs_ln1_symbol_err_cnt;
+ kstat_named_t xpcs_ln2_symbol_err_cnt;
+ kstat_named_t xpcs_ln3_symbol_err_cnt;
+} nxge_xmac_kstat_t, *p_nxge_xmac_kstat_t;
+
+typedef struct _nxge_bmac_kstat {
+ /*
+ * BMAC statistics.
+ */
+ kstat_named_t tx_frame_cnt;
+ kstat_named_t tx_underrun_err;
+ kstat_named_t tx_max_pkt_err;
+ kstat_named_t tx_byte_cnt;
+ kstat_named_t rx_frame_cnt;
+ kstat_named_t rx_byte_cnt;
+ kstat_named_t rx_overflow_err;
+ kstat_named_t rx_align_err_cnt;
+ kstat_named_t rx_crc_err_cnt;
+ kstat_named_t rx_len_err_cnt;
+ kstat_named_t rx_viol_err_cnt;
+ kstat_named_t rx_pause_cnt;
+ kstat_named_t tx_pause_state;
+ kstat_named_t tx_nopause_state;
+} nxge_bmac_kstat_t, *p_nxge_bmac_kstat_t;
+
+
+typedef struct _nxge_fflp_kstat {
+ /*
+ * FFLP statistics.
+ */
+
+ kstat_named_t fflp_tcam_ecc_err;
+ kstat_named_t fflp_tcam_perr;
+ kstat_named_t fflp_vlan_perr;
+ kstat_named_t fflp_hasht_lookup_err;
+ kstat_named_t fflp_access_fail;
+ kstat_named_t fflp_hasht_data_err[MAX_PARTITION];
+} nxge_fflp_kstat_t, *p_nxge_fflp_kstat_t;
+
+typedef struct _nxge_mmac_kstat {
+ kstat_named_t mmac_max_addr_cnt;
+ kstat_named_t mmac_avail_addr_cnt;
+ kstat_named_t mmac_addr1;
+ kstat_named_t mmac_addr2;
+ kstat_named_t mmac_addr3;
+ kstat_named_t mmac_addr4;
+ kstat_named_t mmac_addr5;
+ kstat_named_t mmac_addr6;
+ kstat_named_t mmac_addr7;
+ kstat_named_t mmac_addr8;
+ kstat_named_t mmac_addr9;
+ kstat_named_t mmac_addr10;
+ kstat_named_t mmac_addr11;
+ kstat_named_t mmac_addr12;
+ kstat_named_t mmac_addr13;
+ kstat_named_t mmac_addr14;
+ kstat_named_t mmac_addr15;
+ kstat_named_t mmac_addr16;
+} nxge_mmac_kstat_t, *p_nxge_mmac_kstat_t;
+
+#endif /* _KERNEL */
+
+/*
+ * Prototype definitions.
+ */
+nxge_status_t nxge_init(p_nxge_t);
+void nxge_uninit(p_nxge_t);
+void nxge_get64(p_nxge_t, p_mblk_t);
+void nxge_put64(p_nxge_t, p_mblk_t);
+void nxge_pio_loop(p_nxge_t, p_mblk_t);
+
+#ifndef COSIM
+typedef void (*fptrv_t)();
+timeout_id_t nxge_start_timer(p_nxge_t, fptrv_t, int);
+void nxge_stop_timer(p_nxge_t, timeout_id_t);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_common.h b/usr/src/uts/sun4v/sys/nxge/nxge_common.h
new file mode 100644
index 0000000000..5cd295eb2d
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_common.h
@@ -0,0 +1,483 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_COMMON_H
+#define _SYS_NXGE_NXGE_COMMON_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NXGE_DMA_START B_TRUE
+#define NXGE_DMA_STOP B_FALSE
+
+/*
+ * Default DMA configurations.
+ */
+#define NXGE_RDMA_PER_NIU_PORT (NXGE_MAX_RDCS/NXGE_PORTS_NIU)
+#define NXGE_TDMA_PER_NIU_PORT (NXGE_MAX_TDCS_NIU/NXGE_PORTS_NIU)
+#define NXGE_RDMA_PER_NEP_PORT (NXGE_MAX_RDCS/NXGE_PORTS_NEPTUNE)
+#define NXGE_TDMA_PER_NEP_PORT (NXGE_MAX_TDCS/NXGE_PORTS_NEPTUNE)
+#define NXGE_RDCGRP_PER_NIU_PORT (NXGE_MAX_RDC_GROUPS/NXGE_PORTS_NIU)
+#define NXGE_RDCGRP_PER_NEP_PORT (NXGE_MAX_RDC_GROUPS/NXGE_PORTS_NEPTUNE)
+
+#define NXGE_TIMER_RESO 2
+
+#define NXGE_TIMER_LDG 2
+
+/*
+ * Receive and Transmit DMA definitions
+ */
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+/*
+ * N2/NIU: Maximum descriptors if we need to call
+ * Hypervisor to set up the logical pages
+ * and the driver must use contiguous memory.
+ */
+#define NXGE_NIU_MAX_ENTRY (1 << 9) /* 512 */
+#define NXGE_NIU_CONTIG_RBR_MAX (NXGE_NIU_MAX_ENTRY)
+#define NXGE_NIU_CONTIG_RCR_MAX (NXGE_NIU_MAX_ENTRY)
+#define NXGE_NIU_CONTIG_TX_MAX (NXGE_NIU_MAX_ENTRY)
+#endif
+
+#ifdef _DMA_USES_VIRTADDR
+#ifdef NIU_PA_WORKAROUND
+#define NXGE_DMA_BLOCK (16 * 64 * 4)
+#else
+#define NXGE_DMA_BLOCK 1
+#endif
+#else
+#define NXGE_DMA_BLOCK (64 * 64)
+#endif
+
+#define NXGE_RBR_RBB_MIN (128)
+#define NXGE_RBR_RBB_MAX (64 * 128 -1)
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+#define NXGE_RBR_RBB_DEFAULT 512
+#define NXGE_RBR_SPARE 0
+#else
+#define NXGE_RBR_RBB_DEFAULT (64 * 16) /* x86 hello */
+#define NXGE_RBR_SPARE 0
+#endif
+
+
+#define NXGE_RCR_MIN (NXGE_RBR_RBB_MIN * 2)
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+#define NXGE_RCR_MAX (NXGE_NIU_CONTIG_RCR_MAX)
+#define NXGE_RCR_DEFAULT (512)
+#define NXGE_TX_RING_DEFAULT (512)
+#else
+#ifndef NIU_PA_WORKAROUND
+#define NXGE_RCR_MAX (65355) /* MAX hardware supported */
+#if defined(_BIG_ENDIAN)
+#define NXGE_RCR_DEFAULT (NXGE_RBR_RBB_DEFAULT * 8)
+#else
+#ifdef USE_RX_BIG_BUF
+#define NXGE_RCR_DEFAULT (NXGE_RBR_RBB_DEFAULT * 8)
+#else
+#define NXGE_RCR_DEFAULT (NXGE_RBR_RBB_DEFAULT * 4)
+#endif
+#endif
+#define NXGE_TX_RING_DEFAULT (1024)
+#define NXGE_TX_RING_MAX (64 * 128 - 1)
+#else
+#define NXGE_RCR_DEFAULT (512)
+#define NXGE_TX_RING_DEFAULT (512)
+#define NXGE_RCR_MAX (1024)
+#define NXGE_TX_RING_MAX (1024)
+#endif
+#endif
+
+#define NXGE_TX_RECLAIM 32
+
+/* per receive DMA channel configuration data structure */
+typedef struct nxge_rdc_cfg {
+ uint32_t flag; /* 0: not configured, 1: configured */
+ struct nxge_hw_list *nxge_hw_p;
+ uint32_t partition_id;
+ uint32_t port; /* function number */
+ uint32_t rx_group_id;
+
+ /* Partitioning, DMC function zero. */
+ uint32_t rx_log_page_vld_page0; /* TRUE or FALSE */
+ uint32_t rx_log_page_vld_page1; /* TRUE or FALSE */
+ uint64_t rx_log_mask1;
+ uint64_t rx_log_value1;
+ uint64_t rx_log_mask2;
+ uint64_t rx_log_value2;
+ uint64_t rx_log_page_relo1;
+ uint64_t rx_log_page_relo2;
+ uint64_t rx_log_page_hdl;
+
+ /* WRED parameters, DMC function zero */
+ uint32_t red_enable;
+
+ uint32_t thre_syn;
+ uint32_t win_syn;
+ uint32_t threshold;
+ uint32_t win_non_syn;
+
+ /* RXDMA configuration, DMC */
+ char *rdc_mbaddr_p; /* mailbox address */
+ uint32_t min_flag; /* TRUE for 18 bytes header */
+
+ /* Software Reserved Packet Buffer Offset, DMC */
+ uint32_t sw_offset;
+
+ /* RBR Configuration A */
+ uint64_t rbr_staddr; /* starting address of RBR */
+ uint32_t rbr_nblks; /* # of RBR entries */
+ uint32_t rbr_len; /* # of RBR entries in 64B lines */
+
+ /* RBR Configuration B */
+ uint32_t bksize; /* Block size is fixed. */
+#define RBR_BKSIZE_4K 0
+#define RBR_BKSIZE_8K 1
+#define RBR_BKSIZE_16K 2
+#define RBR_BKSIZE_32K 3
+
+ uint32_t bufsz2;
+#define RBR_BUFSZ2_2K 0
+#define RBR_BUFSZ2_2K_BYTES (2 * 1024)
+#define RBR_BUFSZ2_4K 1
+#define RBR_BUFSZ2_4K_BYTES (4 * 1024)
+#define RBR_BUFSZ2_8K 2
+#define RBR_BUFSZ2_8K_BYTES (8 * 1024)
+#define RBR_BUFSZ2_16K 3
+#define RBR_BUFSZ2_16K_BYTES (16 * 1024)
+
+ uint32_t bufsz1;
+#define RBR_BUFSZ1_1K 0
+#define RBR_BUFSZ1_1K_BYTES 1024
+#define RBR_BUFSZ1_2K 1
+#define RBR_BUFSZ1_2K_BYTES (2 * 1024)
+#define RBR_BUFSZ1_4K 2
+#define RBR_BUFSZ1_4K_BYTES (4 * 1024)
+#define RBR_BUFSZ1_8K 3
+#define RBR_BUFSZ1_8K_BYTES (8 * 1024)
+
+ uint32_t bufsz0;
+#define RBR_BUFSZ0_256B 0
+#define RBR_BUFSZ0_256_BYTES 256
+#define RBR_BUFSZ0_512B 1
+#define RBR_BUFSZ0_512B_BYTES 512
+#define RBR_BUFSZ0_1K 2
+#define RBR_BUFSZ0_1K_BYTES (1024)
+#define RBR_BUFSZ0_2K 3
+#define RBR_BUFSZ0_2K_BYTES (2 * 1024)
+
+ /* Receive buffers added by the software */
+ uint32_t bkadd; /* maximum size is 1 million */
+
+ /* Receive Completion Ring Configuration A */
+ uint32_t rcr_len; /* # of 64B blocks, each RCR is 8B */
+ uint64_t rcr_staddr;
+
+ /* Receive Completion Ring Configuration B */
+ uint32_t pthres; /* packet threshold */
+ uint32_t entout; /* enable timeout */
+ uint32_t timeout; /* timeout value */
+
+ /* Logical Device Group Number */
+ uint16_t rx_ldg;
+ uint16_t rx_ld_state_flags;
+
+ /* Receive DMA Channel Event Mask */
+ uint64_t rx_dma_ent_mask;
+
+ /* 32 bit (set to 1) or 64 bit (set to 0) addressing mode */
+ uint32_t rx_addr_md;
+} nxge_rdc_cfg_t, *p_nxge_rdc_cfg_t;
+
+/*
+ * Per Transmit DMA Channel Configuration Data Structure (32 TDC)
+ */
+typedef struct nxge_tdc_cfg {
+ uint32_t flag; /* 0: not configured 1: configured */
+ struct nxge_hw_list *nxge_hw_p;
+ uint32_t partition_id;
+ uint32_t port; /* function number */
+ /* partitioning, DMC function zero (All 0s for non-partitioning) */
+ uint32_t tx_log_page_vld_page0; /* TRUE or FALSE */
+ uint32_t tx_log_page_vld_page1; /* TRUE or FALSE */
+ uint64_t tx_log_mask1;
+ uint64_t tx_log_value1;
+ uint64_t tx_log_mask2;
+ uint64_t tx_log_value2;
+ uint64_t tx_log_page_relo1;
+ uint64_t tx_log_page_relo2;
+ uint64_t tx_log_page_hdl;
+
+ /* Transmit Ring Configuration */
+ uint64_t tx_staddr;
+ uint64_t tx_rng_len; /* in 64 B Blocks */
+#define TX_MAX_BUF_SIZE 4096
+
+ /* TXDMA configuration, DMC */
+ char *tdc_mbaddr_p; /* mailbox address */
+
+ /* Logical Device Group Number */
+ uint16_t tx_ldg;
+ uint16_t tx_ld_state_flags;
+
+ /* TXDMA event flags */
+ uint64_t tx_event_mask;
+
+ /* Transmit threshold before reclamation */
+ uint32_t tx_rng_threshold;
+#define TX_RING_THRESHOLD (TX_DEFAULT_MAX_GPS/4)
+#define TX_RING_JUMBO_THRESHOLD (TX_DEFAULT_JUMBO_MAX_GPS/4)
+
+ /* For reclaim: a wrap-around counter (packets transmitted) */
+ uint32_t tx_pkt_cnt;
+ /* last packet with the mark bit set */
+ uint32_t tx_lastmark;
+} nxge_tdc_cfg_t, *p_nxge_tdc_cfg_t;
+
+#define RDC_TABLE_ENTRY_METHOD_SEQ 0
+#define RDC_TABLE_ENTRY_METHOD_REP 1
+
+/* per receive DMA channel table group data structure */
+typedef struct nxge_rdc_grp {
+ uint32_t flag; /* 0:not configured 1: configured */
+ uint8_t port;
+ uint8_t partition_id;
+ uint8_t rx_group_id;
+ uint8_t start_rdc; /* assume assigned in sequence */
+ uint8_t max_rdcs;
+ uint8_t def_rdc;
+ uint8_t rdc[NXGE_MAX_RDCS];
+ uint16_t config_method;
+} nxge_rdc_grp_t, *p_nxge_rdc_grp_t;
+
+/* Common RDC and TDC configuration of DMC */
+typedef struct _nxge_dma_common_cfg_t {
+ uint16_t rdc_red_ran_init; /* RED initial seed value */
+
+ /* Transmit Ring */
+} nxge_dma_common_cfg_t, *p_nxge_dma_common_cfg_t;
+
+/*
+ * VLAN and MAC table configurations:
+ * Each VLAN ID should belong to at most one RDC group.
+ * Each port could own multiple RDC groups.
+ * Each MAC should belong to one RDC group.
+ */
+typedef struct nxge_mv_cfg {
+ uint8_t flag; /* 0:unconfigure 1:configured */
+ uint8_t rdctbl; /* RDC channel table group */
+ uint8_t mpr_npr; /* MAC and VLAN preference */
+ uint8_t odd_parity;
+} nxge_mv_cfg_t, *p_nxge_mv_cfg_t;
+
+typedef struct nxge_param_map {
+#if defined(_BIG_ENDIAN)
+ uint32_t rsrvd2:2; /* [30:31] rsrvd */
+ uint32_t remove:1; /* [29] Remove */
+ uint32_t pref:1; /* [28] preference */
+ uint32_t rsrv:4; /* [27:24] preference */
+ uint32_t map_to:8; /* [23:16] map to resource */
+ uint32_t param_id:16; /* [15:0] Param ID */
+#else
+ uint32_t param_id:16; /* [15:0] Param ID */
+ uint32_t map_to:8; /* [23:16] map to resource */
+ uint32_t rsrv:4; /* [27:24] preference */
+ uint32_t pref:1; /* [28] preference */
+ uint32_t remove:1; /* [29] Remove */
+ uint32_t rsrvd2:2; /* [30:31] rsrvd */
+#endif
+} nxge_param_map_t, *p_nxge_param_map_t;
+
+typedef struct nxge_rcr_param {
+#if defined(_BIG_ENDIAN)
+ uint32_t rsrvd2:2; /* [30:31] rsrvd */
+ uint32_t remove:1; /* [29] Remove */
+ uint32_t rsrv:5; /* [28:24] preference */
+ uint32_t rdc:8; /* [23:16] rdc # */
+ uint32_t cfg_val:16; /* [15:0] interrupt parameter */
+#else
+ uint32_t cfg_val:16; /* [15:0] interrupt parameter */
+ uint32_t rdc:8; /* [23:16] rdc # */
+ uint32_t rsrv:5; /* [28:24] preference */
+ uint32_t remove:1; /* [29] Remove */
+ uint32_t rsrvd2:2; /* [30:31] rsrvd */
+#endif
+} nxge_rcr_param_t, *p_nxge_rcr_param_t;
+
+/* Needs to have entries in the ndd table */
+/*
+ * Hardware properties created by fcode.
+ * In order for those properties visible to the user
+ * command ndd, we need to add the following properties
+ * to the ndd defined parameter array and data structures.
+ *
+ * Use default static configuration for x86.
+ */
+typedef struct nxge_hw_pt_cfg {
+ uint32_t partition_id; /* partition Id */
+ uint32_t read_write_mode; /* read write permission mode */
+ uint32_t function_number; /* function number */
+ uint32_t start_tdc; /* start TDC (0 - 31) */
+ uint32_t max_tdcs; /* max TDC in sequence */
+ uint32_t start_rdc; /* start RDC (0 - 31) */
+ uint32_t max_rdcs; /* max rdc in sequence */
+ uint32_t ninterrupts; /* obp interrupts(mac/mif/syserr) */
+ uint32_t mac_ldvid;
+ uint32_t mif_ldvid;
+ uint32_t ser_ldvid;
+ uint32_t def_rdc; /* default RDC */
+ uint32_t drr_wt; /* port DRR weight */
+ uint32_t rx_full_header; /* select the header flag */
+ uint32_t start_grpid; /* starting group ID */
+ uint32_t max_grpids; /* max group ID */
+ uint32_t start_rdc_grpid; /* starting RDC group ID */
+ uint32_t max_rdc_grpids; /* max RDC group ID */
+ uint32_t start_ldg; /* starting logical group # */
+ uint32_t max_ldgs; /* max logical device group */
+ uint32_t max_ldvs; /* max logical devices */
+ uint32_t start_mac_entry; /* where to put the first mac */
+ uint32_t max_macs; /* the max mac entry allowed */
+ uint32_t mac_pref; /* preference over VLAN */
+ uint32_t def_mac_rxdma_grpid; /* default RDC group ID */
+ uint32_t start_vlan; /* starting VLAN ID */
+ uint32_t max_vlans; /* max VLAN ID */
+ uint32_t vlan_pref; /* preference over MAC */
+ uint32_t def_vlan_rxdma_grpid; /* default RDC group Id */
+
+ /* Expand if we have more hardware or default configurations */
+ uint16_t ldg[NXGE_INT_MAX_LDG];
+ uint16_t ldg_chn_start;
+} nxge_hw_pt_cfg_t, *p_nxge_hw_pt_cfg_t;
+
+
+/* per port configuration */
+typedef struct nxge_dma_pt_cfg {
+ uint8_t mac_port; /* MAC port (function) */
+ nxge_hw_pt_cfg_t hw_config; /* hardware configuration */
+
+ uint32_t alloc_buf_size;
+ uint32_t rbr_size;
+ uint32_t rcr_size;
+
+ /*
+ * Configuration for hardware initialization based on the
+ * hardware properties or the default properties.
+ */
+ uint32_t tx_dma_map; /* Transmit DMA channel bit map */
+
+ /* Receive DMA channel */
+ nxge_rdc_grp_t rdc_grps[NXGE_MAX_RDC_GROUPS];
+
+ uint16_t rcr_timeout[NXGE_MAX_RDCS];
+ uint16_t rcr_threshold[NXGE_MAX_RDCS];
+ uint8_t rcr_full_header;
+ uint16_t rx_drr_weight;
+
+ /* Add more stuff later */
+} nxge_dma_pt_cfg_t, *p_nxge_dma_pt_cfg_t;
+
+/* classification configuration */
+typedef struct nxge_class_pt_cfg {
+
+ /* MAC table */
+ nxge_mv_cfg_t mac_host_info[NXGE_MAX_MACS];
+
+ /* VLAN table */
+ nxge_mv_cfg_t vlan_tbl[NXGE_MAX_VLANS];
+ /* class config value */
+ uint32_t init_h1;
+ uint16_t init_h2;
+ uint8_t mcast_rdcgrp;
+ uint8_t mac_rdcgrp;
+ uint32_t class_cfg[TCAM_CLASS_MAX];
+} nxge_class_pt_cfg_t, *p_nxge_class_pt_cfg_t;
+
+/* per Neptune sharable resources among ports */
+typedef struct nxge_common {
+ uint32_t partition_id;
+ boolean_t mode32;
+ /* DMA Channels: RDC and TDC */
+ nxge_rdc_cfg_t rdc_config[NXGE_MAX_RDCS];
+ nxge_tdc_cfg_t tdc_config[NXGE_MAX_TDCS];
+ nxge_dma_common_cfg_t dma_common_config;
+
+ uint32_t timer_res;
+ boolean_t ld_sys_error_set;
+ uint8_t sys_error_owner;
+
+ /* Layer 2/3/4 */
+ uint16_t class2_etype;
+ uint16_t class3_etype;
+
+ /* FCRAM (hashing) */
+ uint32_t hash1_initval;
+ uint32_t hash2_initval;
+} nxge_common_t, *p_nxge_common_t;
+
+/*
+ * Partition (logical domain) configuration per Neptune/NIU.
+ */
+typedef struct nxge_part_cfg {
+ uint32_t rdc_grpbits; /* RDC group bit masks */
+ uint32_t tdc_bitmap; /* bounded TDC */
+ nxge_dma_pt_cfg_t pt_config[NXGE_MAX_PORTS];
+
+ /* Flow Classification Partition (flow partition select register) */
+ uint8_t hash_lookup; /* external lookup is available */
+ uint8_t base_mask; /* select bits in base_h1 to replace */
+ /* bits [19:15} in Hash 1. */
+ uint8_t base_h1; /* value to replace Hash 1 [19:15]. */
+
+ /* Add more here */
+ uint32_t attributes; /* permission and attribute bits */
+#define FZC_SERVICE_ENTITY 0x01
+#define FZC_READ_WRITE 0x02
+#define FZC_READ_ONLY 0x04
+} nxge_part_cfg_t, *p_nxge_part_cfg_t;
+
+typedef struct nxge_hw_list {
+ struct nxge_hw_list *next;
+ nxge_os_mutex_t nxge_cfg_lock;
+ nxge_os_mutex_t nxge_tcam_lock;
+ nxge_os_mutex_t nxge_vlan_lock;
+ nxge_os_mutex_t nxge_mdio_lock;
+ nxge_os_mutex_t nxge_mii_lock;
+
+ nxge_dev_info_t *parent_devp;
+ struct _nxge_t *nxge_p[NXGE_MAX_PORTS];
+ uint32_t ndevs;
+ uint32_t flags;
+ uint32_t magic;
+} nxge_hw_list_t, *p_nxge_hw_list_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_COMMON_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_common_impl.h b/usr/src/uts/sun4v/sys/nxge/nxge_common_impl.h
new file mode 100644
index 0000000000..db0716246c
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_common_impl.h
@@ -0,0 +1,1035 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_COMMON_IMPL_H
+#define _SYS_NXGE_NXGE_COMMON_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NPI_REGH(npi_handle) (npi_handle.regh)
+#define NPI_REGP(npi_handle) (npi_handle.regp)
+
+#if defined(NXGE_DEBUG_DMA) || defined(NXGE_DEBUG_TXC)
+#define __NXGE_STATIC
+#define __NXGE_INLINE
+#else
+#define __NXGE_STATIC static
+#define __NXGE_INLINE inline
+#endif
+
+#ifdef AXIS_DEBUG
+#define AXIS_WAIT (100000)
+#define AXIS_LONG_WAIT (100000)
+#define AXIS_WAIT_W (80000)
+#define AXIS_WAIT_R (100000)
+#define AXIS_WAIT_LOOP (4000)
+#define AXIS_WAIT_PER_LOOP (AXIS_WAIT_R/AXIS_WAIT_LOOP)
+#endif
+
+
+
+#define NO_DEBUG 0x0000000000000000ULL
+#define MDT_CTL 0x0000000000000001ULL
+#define RX_CTL 0x0000000000000002ULL
+#define TX_CTL 0x0000000000000004ULL
+#define OBP_CTL 0x0000000000000008ULL
+
+#define VPD_CTL 0x0000000000000010ULL
+#define DDI_CTL 0x0000000000000020ULL
+#define MEM_CTL 0x0000000000000040ULL
+#define SAP_CTL 0x0000000000000080ULL
+
+#define IOC_CTL 0x0000000000000100ULL
+#define MOD_CTL 0x0000000000000200ULL
+#define DMA_CTL 0x0000000000000400ULL
+#define STR_CTL 0x0000000000000800ULL
+
+#define INT_CTL 0x0000000000001000ULL
+#define SYSERR_CTL 0x0000000000002000ULL
+#define KST_CTL 0x0000000000004000ULL
+#define PCS_CTL 0x0000000000008000ULL
+
+#define MII_CTL 0x0000000000010000ULL
+#define MIF_CTL 0x0000000000020000ULL
+#define FCRAM_CTL 0x0000000000040000ULL
+#define MAC_CTL 0x0000000000080000ULL
+
+#define IPP_CTL 0x0000000000100000ULL
+#define DMA2_CTL 0x0000000000200000ULL
+#define RX2_CTL 0x0000000000400000ULL
+#define TX2_CTL 0x0000000000800000ULL
+
+#define MEM2_CTL 0x0000000001000000ULL
+#define MEM3_CTL 0x0000000002000000ULL
+#define NXGE_CTL 0x0000000004000000ULL
+#define NDD_CTL 0x0000000008000000ULL
+#define NDD2_CTL 0x0000000010000000ULL
+
+#define TCAM_CTL 0x0000000020000000ULL
+#define CFG_CTL 0x0000000040000000ULL
+#define CFG2_CTL 0x0000000080000000ULL
+
+#define FFLP_CTL TCAM_CTL | FCRAM_CTL
+
+#define VIR_CTL 0x0000000100000000ULL
+#define VIR2_CTL 0x0000000200000000ULL
+
+#define NXGE_NOTE 0x0000001000000000ULL
+#define NXGE_ERR_CTL 0x0000002000000000ULL
+
+#define DUMP_ALWAYS 0x2000000000000000ULL
+
+/* NPI Debug and Error defines */
+#define NPI_RDC_CTL 0x0000000000000001ULL
+#define NPI_TDC_CTL 0x0000000000000002ULL
+#define NPI_TXC_CTL 0x0000000000000004ULL
+#define NPI_IPP_CTL 0x0000000000000008ULL
+
+#define NPI_XPCS_CTL 0x0000000000000010ULL
+#define NPI_PCS_CTL 0x0000000000000020ULL
+#define NPI_ESR_CTL 0x0000000000000040ULL
+#define NPI_BMAC_CTL 0x0000000000000080ULL
+#define NPI_XMAC_CTL 0x0000000000000100ULL
+#define NPI_MAC_CTL NPI_BMAC_CTL | NPI_XMAC_CTL
+
+#define NPI_ZCP_CTL 0x0000000000000200ULL
+#define NPI_TCAM_CTL 0x0000000000000400ULL
+#define NPI_FCRAM_CTL 0x0000000000000800ULL
+#define NPI_FFLP_CTL NPI_TCAM_CTL | NPI_FCRAM_CTL
+
+#define NPI_VIR_CTL 0x0000000000001000ULL
+#define NPI_PIO_CTL 0x0000000000002000ULL
+#define NPI_VIO_CTL 0x0000000000004000ULL
+
+#define NPI_REG_CTL 0x0000000040000000ULL
+#define NPI_CTL 0x0000000080000000ULL
+#define NPI_ERR_CTL 0x0000000080000000ULL
+
+#if defined(SOLARIS) && defined(_KERNEL)
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/dditypes.h>
+#include <sys/ethernet.h>
+
+#ifdef NXGE_DEBUG
+#define NXGE_DEBUG_MSG(params) nxge_debug_msg params
+#else
+#define NXGE_DEBUG_MSG(params)
+#endif
+
+#if 1
+#define NXGE_ERROR_MSG(params) nxge_debug_msg params
+#define NXGE_WARN_MSG(params) nxge_debug_msg params
+#else
+#define NXGE_ERROR_MSG(params)
+#define NXGE_WARN_MSG(params)
+
+#endif
+
+
+typedef kmutex_t nxge_os_mutex_t;
+typedef krwlock_t nxge_os_rwlock_t;
+
+typedef dev_info_t nxge_dev_info_t;
+typedef ddi_iblock_cookie_t nxge_intr_cookie_t;
+
+typedef ddi_acc_handle_t nxge_os_acc_handle_t;
+typedef nxge_os_acc_handle_t npi_reg_handle_t;
+typedef uint64_t npi_reg_ptr_t;
+
+typedef ddi_dma_handle_t nxge_os_dma_handle_t;
+typedef struct _nxge_dma_common_t nxge_os_dma_common_t;
+typedef struct _nxge_block_mv_t nxge_os_block_mv_t;
+typedef frtn_t nxge_os_frtn_t;
+
+#define NXGE_MUTEX_DRIVER MUTEX_DRIVER
+#define MUTEX_INIT(lock, name, type, arg) \
+ mutex_init(lock, name, type, arg)
+#define MUTEX_ENTER(lock) mutex_enter(lock)
+#define MUTEX_TRY_ENTER(lock) mutex_tryenter(lock)
+#define MUTEX_EXIT(lock) mutex_exit(lock)
+#define MUTEX_DESTROY(lock) mutex_destroy(lock)
+
+#define RW_INIT(lock, name, type, arg) rw_init(lock, name, type, arg)
+#define RW_ENTER_WRITER(lock) rw_enter(lock, RW_WRITER)
+#define RW_ENTER_READER(lock) rw_enter(lock, RW_READER)
+#define RW_TRY_ENTER(lock, type) rw_tryenter(lock, type)
+#define RW_EXIT(lock) rw_exit(lock)
+#define RW_DESTROY(lock) rw_destroy(lock)
+#define KMEM_ALLOC(size, flag) kmem_alloc(size, flag)
+#define KMEM_ZALLOC(size, flag) kmem_zalloc(size, flag)
+#define KMEM_FREE(buf, size) kmem_free(buf, size)
+
+#define NXGE_DELAY(microseconds) (drv_usecwait(microseconds))
+
+#define NXGE_PIO_READ8(handle, devaddr, offset) \
+ (ddi_get8(handle, (uint8_t *)((caddr_t)devaddr + offset)))
+
+#define NXGE_PIO_READ16(handle, devaddr, offset) \
+ (ddi_get16(handle, (uint16_t *)((caddr_t)devaddr + offset)))
+
+#define NXGE_PIO_READ32(handle, devaddr, offset) \
+ (ddi_get32(handle, (uint32_t *)((caddr_t)devaddr + offset)))
+
+#define NXGE_PIO_READ64(handle, devaddr, offset) \
+ (ddi_get64(handle, (uint64_t *)((caddr_t)devaddr + offset)))
+
+#define NXGE_PIO_WRITE8(handle, devaddr, offset, data) \
+ (ddi_put8(handle, (uint8_t *)((caddr_t)devaddr + offset), data))
+
+#define NXGE_PIO_WRITE16(handle, devaddr, offset, data) \
+ (ddi_get16(handle, (uint16_t *)((caddr_t)devaddr + offset), data))
+
+#define NXGE_PIO_WRITE32(handle, devaddr, offset, data) \
+ (ddi_put32(handle, (uint32_t *)((caddr_t)devaddr + offset), data))
+
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) \
+ (ddi_put64(handle, (uint64_t *)((caddr_t)devaddr + offset), data))
+
+#define NXGE_NPI_PIO_READ8(npi_handle, offset) \
+ (ddi_get8(NPI_REGH(npi_handle), \
+ (uint8_t *)(NPI_REGP(npi_handle) + offset)))
+
+#define NXGE_NPI_PIO_READ16(npi_handle, offset) \
+ (ddi_get16(NPI_REGH(npi_handle), \
+ (uint16_t *)(NPI_REGP(npi_handle) + offset)))
+
+#define NXGE_NPI_PIO_READ32(npi_handle, offset) \
+ (ddi_get32(NPI_REGH(npi_handle), \
+ (uint32_t *)(NPI_REGP(npi_handle) + offset)))
+
+#ifdef SW_SIM
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ (*(uint64_t *)(NPI_REGP(npi_handle) + offset))
+
+#elif AXIS_DEBUG
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ ddi_get64(NPI_REGH(npi_handle), \
+ (uint64_t *)(NPI_REGP(npi_handle) + offset));
+#else
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ (ddi_get64(NPI_REGH(npi_handle), \
+ (uint64_t *)(NPI_REGP(npi_handle) + offset)))
+#endif
+
+#define NXGE_NPI_PIO_WRITE8(npi_handle, offset, data) \
+ (ddi_put8(NPI_REGH(npi_handle), \
+ (uint8_t *)(NPI_REGP(npi_handle) + offset), data))
+
+#define NXGE_NPI_PIO_WRITE16(npi_handle, offset, data) \
+ (ddi_put16(NPI_REGH(npi_handle), \
+ (uint16_t *)(NPI_REGP(npi_handle) + offset), data))
+
+#define NXGE_NPI_PIO_WRITE32(npi_handle, offset, data) \
+ (ddi_put32(NPI_REGH(npi_handle), \
+ (uint32_t *)(NPI_REGP(npi_handle) + offset), data))
+
+#ifdef SW_SIM
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) \
+ (*((uint64_t *)(NPI_REGP(npi_handle) + (uint64_t)offset)) = \
+ (uint64_t)data);
+#elif defined(AXIS_DEBUG) && !defined(LEGION)
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) { \
+ ddi_put64(NPI_REGH(npi_handle), \
+ (uint64_t *)(NPI_REGP(npi_handle) + offset), data); \
+}
+#else
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) \
+ (ddi_put64(NPI_REGH(npi_handle), \
+ (uint64_t *)(NPI_REGP(npi_handle) + offset), data))
+
+#endif
+
+#define NXGE_MEM_PIO_READ8(npi_handle) \
+ (ddi_get8(NPI_REGH(npi_handle), (uint8_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ16(npi_handle) \
+ (ddi_get16(NPI_REGH(npi_handle), (uint16_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ32(npi_handle) \
+ (ddi_get32(NPI_REGH(npi_handle), (uint32_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ64(npi_handle) \
+ (ddi_get64(NPI_REGH(npi_handle), (uint64_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_WRITE8(npi_handle, data) \
+ (ddi_put8(NPI_REGH(npi_handle), (uint8_t *)NPI_REGP(npi_handle), data))
+
+#define NXGE_MEM_PIO_WRITE16(npi_handle, data) \
+ (ddi_put16(NPI_REGH(npi_handle), \
+ (uint16_t *)NPI_REGP(npi_handle), data))
+
+#define NXGE_MEM_PIO_WRITE32(npi_handle, data) \
+ (ddi_put32(NPI_REGH(npi_handle), \
+ (uint32_t *)NPI_REGP(npi_handle), data))
+
+#define NXGE_MEM_PIO_WRITE64(npi_handle, data) \
+ (ddi_put64(NPI_REGH(npi_handle), \
+ (uint64_t *)NPI_REGP(npi_handle), data))
+
+#define SERVICE_LOST DDI_SERVICE_LOST
+#define SERVICE_DEGRADED DDI_SERVICE_DEGRADED
+#define SERVICE_UNAFFECTED DDI_SERVICE_UNAFFECTED
+#define SERVICE_RESTORED DDI_SERVICE_RESTORED
+
+#define DATAPATH_FAULT DDI_DATAPATH_FAULT
+#define DEVICE_FAULT DDI_DEVICE_FAULT
+#define EXTERNAL_FAULT DDI_EXTERNAL_FAULT
+
+#define NOTE_LINK_UP DL_NOTE_LINK_UP
+#define NOTE_LINK_DOWN DL_NOTE_LINK_DOWN
+#define NOTE_SPEED DL_NOTE_SPEED
+#define NOTE_PHYS_ADDR DL_NOTE_PHYS_ADDR
+#define NOTE_AGGR_AVAIL DL_NOTE_AGGR_AVAIL
+#define NOTE_AGGR_UNAVAIL DL_NOTE_AGGR_UNAVAIL
+
+#define FM_REPORT_FAULT(nxgep, impact, location, msg)\
+ ddi_dev_report_fault(nxgep->dip, impact, location, msg)
+#define FM_CHECK_DEV_HANDLE(nxgep)\
+ ddi_check_acc_handle(nxgep->dev_regs->nxge_regh)
+#define FM_GET_DEVSTATE(nxgep)\
+ ddi_get_devstate(nxgep->dip)
+#ifdef NXGE_FM
+#define FM_SERVICE_RESTORED(nxgep)\
+ ddi_fm_service_impact(nxgep->dip, DDI_SERVICE_RESTORED)
+#define NXGE_FM_REPORT_ERROR(nxgep, portn, chan, ereport_id)\
+ nxge_fm_report_error(nxgep, portn, chan, ereport_id)
+#else
+#define FM_SERVICE_RESTORED(nxgep)
+#define NXGE_FM_REPORT_ERROR(nxgep, portn, chan, ereport_id)
+#endif
+
+#elif defined(LINUX) && defined(__KERNEL_)
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
+/* #include <linux/mii.h> */
+#include <linux/if_vlan.h>
+#include <linux/llc.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+
+#include <net/checksum.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+typedef unsigned char uchar_t;
+typedef unsigned short ushort_t;
+typedef unsigned int uint_t;
+typedef unsigned long ulong_t;
+
+#define uintptr_t unsigned long
+
+#define ETHERADDRL ETH_ALEN
+/*
+ * Ethernet address - 6 octets
+ */
+struct ether_addr {
+ uchar_t ether_addr_octet[ETHERADDRL];
+};
+
+typedef struct ether_addr ether_addr_st, *p_ether_addr_t;
+
+typedef enum {
+#undef B_FALSE
+ B_FALSE = 0,
+#undef B_TRUE
+ B_TRUE = 1
+} boolean_t;
+
+typedef enum {
+ BKSIZE_4K,
+ BKSIZE_8K,
+ BKSIZE_16K,
+ BKSIZE_32K
+} nxge_rx_block_size_t;
+
+#ifdef NXGE_DEBUG
+#define NXGE_DEBUG_MSG(params) nxge_debug_msg params
+#define NXGE_WARN_MSG(params) nxge_debug_msg params
+#else
+#define NXGE_DEBUG_MSG(params)
+#define NXGE_WARN_MSG(params)
+#endif
+
+#define NXGE_ERROR_MSG(params) nxge_debug_msg params
+
+#define NPI_INPUT_ERR(funcname, param, val) \
+ printk(KERN_ERR "%s: Invalid Input: %s <0x%x>\n", funcname, param, \
+ (int)val);
+
+#define NPI_HW_ERR(funcname, reg, val) \
+ printk(KERN_ERR "%s: HW Error: %s <0x%x>\n", funcname, reg, (int)val);
+
+
+#define IS_PORT_NUM_VALID(portn) \
+ (portn < 4)
+
+
+typedef spinlock_t nxge_os_mutex_t;
+typedef rwlock_t nxge_os_rwlock_t;
+
+typedef struct pci_dev nxge_dev_info_t;
+typedef void * nxge_intr_cookie_t;
+
+typedef void * nxge_os_acc_handle_t;
+typedef nxge_os_acc_handle_t npi_reg_handle_t;
+typedef char *npi_reg_ptr_t;
+
+typedef void * nxge_os_dma_handle_t;
+typedef void nxge_os_dma_common_t;
+typedef void nxge_os_block_mv_t;
+typedef int nxge_os_frtn_t;
+
+#define MUTEX_INIT(lock, nm, tp, arg) spin_lock_init((lock))
+#define MUTEX_ENTER(lock) spin_lock((lock))
+#define MUTEX_TRY_ENTER(lock) spin_trylock((lock))
+#define MUTEX_EXIT(lock) spin_unlock((lock))
+#define MUTEX_ENTER_INT(lock, flags) spin_lock_irqsave(lock, flags)
+#define MUTEX_EXIT_INT(lock, flags) spin_unlock_irqrestore(lock, flags)
+#define MUTEX_DESTROY(lock)
+
+#define RW_INIT(lock, nm, tp, arg) rw_lock_init((lock))
+#define RW_ENTER_WRITER(lock) write_lock(lock)
+#define RW_ENTER_READER(lock) read_lock(lock)
+#define RW_EXIT(lock) write_unlock(lock)
+#define RW_EXIT_READ(lock) read_unlock(lock)
+#define RW_DESTROY(lock)
+
+#define NXGE_DELAY(microseconds) (udelay(microseconds))
+
+static inline void * nxge_kzalloc(size_t size, int flag)
+{
+ void * ptr = kmalloc(size, flag);
+ if (ptr != NULL)
+ memset(ptr, 0, size);
+
+ return (ptr);
+}
+
+#define KMEM_ALLOC(size, flag) kmalloc(size, flag)
+#define KMEM_ZALLOC(size, flag) nxge_kzalloc(size, flag)
+#define KMEM_FREE(buf, size) kfree(buf)
+
+#ifndef readq
+static inline uint64_t readq(void *addr)
+{
+ uint64_t ret = readl(addr + 4);
+ ret <<= 32;
+ ret |= readl(addr);
+
+ return (ret);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(uint64_t val, void *addr)
+{
+ writel((uint32_t)(val), addr);
+ writel((uint32_t)(val >> 32), (addr + 4));
+}
+
+/*
+ * In 32 bit modes, some registers have to be written in a
+ * particular order to expect correct hardware operation. The
+ * macro SPECIAL_REG_WRITE is used to perform such ordered
+ * writes. Defines UF(Upper First) and LF(Lower First) will
+ * be used to specify the required write order.
+ */
+#define UF 1
+#define LF 2
+static inline void SPECIAL_REG_WRITE(uint64_t val, void *addr, int order)
+{
+ if (order == LF) {
+ writel((uint32_t)(val), addr);
+ writel((uint32_t)(val >> 32), (addr + 4));
+ } else {
+ writel((uint32_t)(val >> 32), (addr + 4));
+ writel((uint32_t)(val), addr);
+ }
+}
+#else
+#define SPECIAL_REG_WRITE(val, addr, dummy) writeq(val, addr)
+#endif
+
+#define NXGE_PIO_READ8(handle, devaddr, offset) \
+ (readb((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ16(handle, devaddr, offset) \
+ (readw((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ32(handle, devaddr, offset) \
+ (readl((caddr_t)devaddr + offset))
+
+#ifdef SW_SIM
+#define NXGE_PIO_READ64(handle, devaddr, offset) \
+ (*((uint64_t *)(devaddr + offset)))
+#elif AXIS_DEBUG
+#define NXGE_PIO_READ64(handle, devaddr, offset) { \
+ readq((caddr_t)devaddr + offset); \
+ mdelay(100); \
+}
+#else
+#define NXGE_PIO_READ64(handle, devaddr, offset) \
+ (readq((caddr_t)devaddr + offset))
+#endif
+
+#define NXGE_PIO_WRITE8(handle, devaddr, offset, data) \
+ (writeb(data, ((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_WRITE16(handle, devaddr, offset, data) \
+ (writew(data, ((caddr_t)devaddr + offset)))
+
+#define NXGE_PIO_WRITE32(handle, devaddr, offset, data) \
+ (writel(data, ((caddr_t)devaddr + offset)))
+
+#ifdef SW_SIM
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) \
+ (*((uint64_t *)(devaddr + offset)) = \
+ (uint64_t)data);
+#elif AXIS_DEBUG
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) { \
+ mdelay(100); \
+ writeq(data, ((caddr_t)devaddr + offset)); \
+}
+#else
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) \
+ (writeq(data, ((caddr_t)devaddr + offset)))
+#endif
+
+#define NXGE_NPI_PIO_READ8(npi_handle, offset) \
+ (readb(NPI_REGP(npi_handle) + offset))
+
+#define NXGE_NPI_PIO_READ16(npi_handle, offset) \
+ (readw(NPI_REGP(npi_handle) + offset))
+
+#define NXGE_NPI_PIO_READ32(npi_handle, offset) \
+ (readl(NPI_REGP(npi_handle) + offset))
+
+#ifndef SW_SIM
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ (readq(NPI_REGP(npi_handle) + offset))
+#else
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ (*((uint64_t *)(NPI_REGP(npi_handle) + offset)))
+#endif /* SW_SIM */
+
+#define NXGE_NPI_PIO_WRITE8(npi_handle, offset, data) \
+ (writeb(data, NPI_REGP(npi_handle) + offset))
+
+#define NXGE_NPI_PIO_WRITE16(npi_handle, offset, data) \
+ (writew(data, NPI_REGP(npi_handle) + offset))
+
+#define NXGE_NPI_PIO_WRITE32(npi_handle, offset, data) \
+ (writel(data, NPI_REGP(npi_handle) + offset))
+
+#ifndef SW_SIM
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) \
+ (writeq(data, NPI_REGP(npi_handle) + offset))
+#else
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) \
+ (*((uint64_t *)(NPI_REGP(npi_handle) + (uint64_t)offset)) = \
+ (uint64_t)data);
+#endif /* SW_SIM */
+
+#define NXGE_MEM_PIO_READ8(npi_handle) (*((uint8_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ16(npi_handle) (*((uint16_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ32(npi_handle) (*((uint32_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ64(npi_handle) (*((uint64_t *)NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_WRITE8(npi_handle, data) \
+ (*((uint8_t *)NPI_REGP(npi_handle))) = ((uint8_t)data)
+
+#define NXGE_MEM_PIO_WRITE16(npi_handle, data) \
+ (*((uint16_t *)NPI_REGP(npi_handle))) = ((uint16_t)data)
+
+#define NXGE_MEM_PIO_WRITE32(npi_handle, data) \
+ (*((uint32_t *)NPI_REGP(npi_handle))) = ((uint32_t)data)
+
+#define NXGE_MEM_PIO_WRITE64(npi_handle, data) \
+ (*((uint64_t *)NPI_REGP(npi_handle))) = ((uint64_t)data)
+
+#elif defined(COSIM)
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#if defined(SOLARIS) && !defined(IODIAG)
+#include <sys/varargs.h>
+#include <ne_sim_solaris.h>
+#endif
+
+#ifdef NXGE_DEBUG
+#define NXGE_DEBUG_MSG(params) nxge_debug_msg params
+#define NXGE_ERROR_MSG(params) nxge_debug_msg params
+#else
+#define NXGE_DEBUG_MSG(params)
+#define NXGE_ERROR_MSG(params)
+#endif
+
+#if !defined(ETHERADDRL)
+#define ETHERADDRL 6
+
+/*
+ * Ethernet address - 6 octets
+ */
+struct ether_addr {
+ uchar_t ether_addr_octet[ETHERADDRL];
+};
+
+typedef struct ether_addr ether_addr_st, *p_ether_addr_t;
+#endif
+
+#ifdef LINUX
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifndef COSIM_LINUX_DEF
+#define COSIM_LINUX_DEF
+typedef uint8_t uchar_t;
+typedef uint32_t uint_t;
+typedef uint64_t dma_addr_t;
+
+typedef enum {
+#undef B_FALSE
+ B_FALSE = 0,
+#undef B_TRUE
+ B_TRUE = 1
+} boolean_t;
+
+#endif
+
+typedef enum {
+ BKSIZE_4K,
+ BKSIZE_8K,
+ BKSIZE_16K,
+ BKSIZE_32K
+} nxge_rx_block_size_t;
+
+#define IS_PORT_NUM_VALID(portn) \
+ (portn < 4)
+
+#define GFP_KERNEL 0
+
+#endif /* LINUX in COSIM */
+
+#include <ht_client.h>
+#include <ht_lib.h>
+
+#include <pthread.h>
+
+
+typedef pthread_mutex_t nxge_os_mutex_t;
+typedef unsigned int nxge_os_rwlock_t;
+
+typedef void * nxge_dev_info_t;
+typedef void * nxge_intr_cookie_t;
+typedef void * nxge_os_dma_handle_t;
+typedef void * nxge_os_acc_handle_t;
+typedef nxge_os_acc_handle_t npi_reg_handle_t;
+typedef uint64_t npi_reg_ptr_t;
+
+#if defined(IODIAG)
+#define timeout(a, b, c) ()
+#define untimeout(a) ()
+#define drv_usectohz(a) ()
+#define drv_usecwait(a)
+#define ether_cmp(a, b) (bcmp((caddr_t)a, (caddr_t)b, 6))
+
+typedef int nxge_os_dma_common_t;
+typedef int nxge_os_block_mv_t;
+typedef int nxge_os_frtn_t;
+typedef void * p_mblk_t;
+typedef void * MBLKP;
+
+#define NXGE_MUTEX_DRIVER NULL
+#define MUTEX_INIT(lock, name, type, arg) pthread_mutex_init(lock, NULL)
+
+#define MUTEX_ENTER(lock) pthread_mutex_lock((pthread_mutex_t *)lock)
+
+#define MUTEX_TRY_ENTER(lock) pthread_mutex_trylock(lock)
+
+#define MUTEX_EXIT(lock) pthread_mutex_unlock(lock)
+
+#define MUTEX_ENTER_INT(lock, flags) MUTEX_ENTER(lock)
+
+#define MUTEX_EXIT_INT(lock, flags) MUTEX_EXIT(lock)
+
+#define MUTEX_DESTROY(lock) pthread_mutex_destroy(lock)
+
+#else
+typedef struct _nxge_dma_common_t nxge_os_dma_common_t;
+typedef struct _nxge_block_mv_t nxge_os_block_mv_t;
+typedef frtn_t nxge_os_frtn_t;
+
+#define NXGE_MUTEX_DRIVER NULL
+#define MUTEX_INIT(lock, name, type, arg)
+#define MUTEX_ENTER(lock)
+#define MUTEX_TRY_ENTER(lock)
+#define MUTEX_EXIT(lock)
+#define MUTEX_ENTER_INT(lock, flags) MUTEX_ENTER(lock)
+#define MUTEX_EXIT_INT(lock, flags) MUTEX_EXIT(lock)
+#define MUTEX_DESTROY(lock)
+#endif
+
+#define KMEM_ALLOC(size, flag) malloc(size)
+#if defined(IODIAG)
+#define KMEM_ZALLOC(size, flag) kmem_zalloc(size, flag)
+#else
+#define KMEM_ZALLOC(size, flag) malloc(size)
+#endif
+#define KMEM_FREE(buf, size) free(buf)
+#define RW_INIT(lock, name, type, arg)
+#define RW_ENTER_WRITER(lock)
+#define RW_ENTER_READER(lock)
+#define RW_TRY_ENTER(lock, type)
+#define RW_EXIT(lock)
+#define RW_EXIT_READ(lock)
+#define RW_DESTROY(lock)
+#define NXGE_NOTIFY_NETWORK_STACK(nxgep, event)
+#define FM_REPORT_FAULT(nxgep, impact, location, msg)
+#define FM_CHECK_DEV_HANDLE(nxgep) NULL
+#define FM_SERVICE_RESTORED(nxgep)
+#define FM_GET_DEVSTATE(nxgep) NULL
+#define NXGE_FM_REPORT_ERROR(nxgep, portn, chan, ereport_id)
+#define SERVICE_LOST NULL
+#define SERVICE_DEGRADED NULL
+#define SERVICE_UNAFFECTED NULL
+#define SERVICE_RESTORED NULL
+
+#define DATAPATH_FAULT NULL
+#define DEVICE_FAULT NULL
+#define EXTERNAL_FAULT NULL
+
+#define NOTE_LINK_UP NULL
+#define NOTE_LINK_DOWN NULL
+#define NOTE_SPEED NULL
+#define NOTE_PHYS_ADDR NULL
+#define NOTE_AGGR_AVAIL NULL
+#define NOTE_AGGR_UNAVAIL NULL
+
+#define kmem_free(buf, size) free(buf)
+
+
+#define NXGE_DELAY(microseconds)
+
+#define NXGE_PIO_READ8(handle, devaddr, offset) \
+ (*(uint8_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ16(handle, devaddr, offset) \
+ (*(uint16_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ32(handle, devaddr, offset) \
+ (*(uint32_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ64(handle, devaddr, offset) \
+ (*(uint64_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_WRITE8(handle, devaddr, offset, data) \
+ (*((uint8_t *)((caddr_t)devaddr + offset)) = (uint8_t)data);
+
+#define NXGE_PIO_WRITE16(handle, devaddr, offset, data) \
+ (*((uint16_t *)((caddr_t)devaddr + offset)) = (uint16_t)data);
+
+#define NXGE_PIO_WRITE32(handle, devaddr, offset, data) \
+ (*((uint32_t *)((caddr_t)devaddr + offset)) = (uint32_t)data);
+
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) \
+ (*((uint64_t *)((caddr_t)devaddr + offset)) = (uint64_t)data);
+
+#ifdef IODIAG_NEPTUNE
+#define NXGE_NPI_PIO_WRITE64(handle, offset, value) { \
+ htSetQWord((uint64_t)offset, value); \
+ us_delay(100000); \
+}
+#else
+#define NXGE_NPI_PIO_WRITE64(handle, offset, value) \
+ htSetQWord((uint64_t)offset, value)
+#endif
+
+#define NXGE_NPI_PIO_WRITE32(handle, offset, value) \
+ htSetDWord((uint64_t)offset, value)
+
+#define NXGE_NPI_PIO_READ64(handle, offset) \
+ htread64((uint64_t)offset)
+
+#define NXGE_NPI_PIO_READ32(handle, offset) \
+ htread32((uint64_t)offset)
+
+#define NXGE_MEM_PIO_READ8(npi_handle) (*(uint8_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ16(npi_handle) (*(uint16_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ32(npi_handle) (*(uint32_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ64(npi_handle) (*(uint64_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_WRITE8(npi_handle, data) \
+ (*((uint8_t *)NPI_REGP(npi_handle)) = (uint8_t)data);
+
+#define NXGE_MEM_PIO_WRITE16(npi_handle, data) \
+ (*((uint16_t *)NPI_REGP(npi_handle)) = (uint16_t)data);
+
+#define NXGE_MEM_PIO_WRITE32(npi_handle, data) \
+ (*((uint32_t *)NPI_REGP(npi_handle)) = (uint32_t)data);
+
+#define NXGE_MEM_PIO_WRITE64(npi_handle, data) \
+ (*((uint64_t *)NPI_REGP(npi_handle)) = (uint64_t)data);
+
+#define NPI_INPUT_ERR(funcname, param, val) \
+ printf("%s: Invalid Input: %s <0x%x>\n", funcname, param, (int)val);
+
+#define NPI_HW_ERR(funcname, reg, val) \
+ printf("%s: HW Error: %s <0x%x>\n", funcname, reg, (int)val);
+
+
+
+#elif defined(SW_SIM)
+typedef unsigned int nxge_os_mutex_t;
+typedef unsigned int nxge_os_rwlock_t;
+
+typedef unsigned int nxge_dev_info_t;
+typedef void * nxge_intr_cookie_t;
+typedef void * nxge_os_acc_handle_t;
+typedef nxge_os_acc_handle_t npi_reg_handle_t;
+typedef uint64_t npi_reg_ptr_t;
+
+typedef unsigned int nxge_os_dma_handle_t;
+typedef unsigned int nxge_os_dma_common_t;
+typedef unsigned int nxge_os_block_mv_t;
+typedef int nxge_os_frtn_t;
+typedef void * p_mblk_t;
+
+typedef struct ether_addr ether_addr_st, *p_ether_addr_t;
+#define NXGE_MUTEX_DRIVER MUTEX_DRIVER
+#define MUTEX_INIT(lock, name, type, arg) \
+ mutex_init(lock, name, type, arg)
+#define MUTEX_ENTER(lock) mutex_enter(lock)
+#define MUTEX_TRY_ENTER(lock) mutex_tryenter(lock)
+#define MUTEX_EXIT(lock) mutex_exit(lock)
+#define MUTEX_DESTROY(lock) mutex_destroy(lock)
+
+#define RW_INIT(lock, nm, tp, arg)
+#define RW_ENTER_WRITER(lock)
+#define RW_ENTER_READER(lock)
+#define RW_EXIT(lock)
+#define RW_DESTROY(lock)
+
+#define NXGE_DELAY(microseconds)
+
+#define NXGE_PIO_READ8(handle, devaddr, offset) \
+ (*(uint8_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ16(handle, devaddr, offset) \
+ (*(uint16_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ32(handle, devaddr, offset) \
+ (*(uint32_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_READ64(handle, devaddr, offset) \
+ (*(uint64_t *)((caddr_t)devaddr + offset))
+
+#define NXGE_PIO_WRITE8(handle, devaddr, offset, data) \
+ (*((uint8_t *)((caddr_t)devaddr + offset)) = (uint8_t)data);
+
+#define NXGE_PIO_WRITE16(handle, devaddr, offset, data) \
+ (*((uint16_t *)((caddr_t)devaddr + offset)) = (uint16_t)data);
+
+#define NXGE_PIO_WRITE32(handle, devaddr, offset, data) \
+ (*((uint32_t *)((caddr_t)devaddr + offset)) = (uint32_t)data);
+
+#define NXGE_PIO_WRITE64(handle, devaddr, offset, data) \
+ (*((uint64_t *)((caddr_t)devaddr + offset)) = (uint64_t)data);
+
+
+#define NXGE_NPI_PIO_READ8(npi_handle, offset) \
+ (*((uint8_t *)(NPI_REGP(npi_handle) + offset)))
+
+#define NXGE_NPI_PIO_READ16(npi_handle, offset) \
+ (*((uint16_t *)(NPI_REGP(npi_handle) + offset)))
+
+#define NXGE_NPI_PIO_READ32(npi_handle, offset) \
+ (*((uint32_t *)(NPI_REGP(npi_handle) + offset)));
+
+#define NXGE_NPI_PIO_READ64(npi_handle, offset) \
+ (*(uint64_t *)(NPI_REGP(npi_handle) + offset));
+
+#define NXGE_NPI_PIO_WRITE8(npi_handle, offset, data) \
+ (*((uint8_t *)(NPI_REGP(npi_handle) + offset)) = (uint8_t)data);
+
+#define NXGE_NPI_PIO_WRITE16(npi_handle, offset, data) \
+ (*((uint16_t *)(NPI_REGP(npi_handle) + offset)) = (uint16_t)data);
+
+#define NXGE_NPI_PIO_WRITE32(npi_handle, offset, data) \
+ (*((uint32_t *)(NPI_REGP(npi_handle) + offset)) = (uint32_t)data);
+
+#define NXGE_NPI_PIO_WRITE64(npi_handle, offset, data) \
+ (*((uint64_t *)(NPI_REGP(npi_handle) + (uint64_t)offset)) = \
+ (uint64_t)data);
+
+#define NXGE_MEM_PIO_READ8(npi_handle) (*(uint8_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ16(npi_handle) (*(uint16_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ32(npi_handle) (*(uint32_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_READ64(npi_handle) (*(uint64_t *)(NPI_REGP(npi_handle)))
+
+#define NXGE_MEM_PIO_WRITE8(npi_handle, data) \
+ (*((uint8_t *)NPI_REGP(npi_handle)) = (uint8_t)data);
+
+#define NXGE_MEM_PIO_WRITE16(npi_handle, data) \
+ (*((uint16_t *)NPI_REGP(npi_handle)) = (uint16_t)data);
+
+#define NXGE_MEM_PIO_WRITE32(npi_handle, data) \
+ (*((uint32_t *)NPI_REGP(npi_handle)) = (uint32_t)data);
+
+#define NXGE_MEM_PIO_WRITE64(npi_handle, data) \
+ (*((uint64_t *)NPI_REGP(npi_handle)) = (uint64_t)data);
+
+
+#define NPI_INPUT_ERR(funcname, param, val) \
+ printf("%s: Invalid Input: %s <0x%x>\n", funcname, param, (int)val);
+
+#define NPI_HW_ERR(funcname, reg, val) \
+ printf("%s: HW Error: %s <0x%x>\n", funcname, reg, (int)val);
+
+
+#endif
+
+#if defined(REG_TRACE)
+#define NXGE_REG_RD64(handle, offset, val_p) {\
+ *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\
+ npi_rtrace_update(handle, B_FALSE, &npi_rtracebuf, (uint32_t)offset, \
+ (uint64_t)(*(val_p)));\
+}
+#elif defined(REG_SHOW)
+ /*
+ * Send 0xbadbad to tell rs_show_reg that we do not have
+ * a valid RTBUF index to pass
+ */
+#define NXGE_REG_RD64(handle, offset, val_p) {\
+ *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\
+ rt_show_reg(0xbadbad, B_FALSE, (uint32_t)offset, (uint64_t)(*(val_p)));\
+}
+#elif defined(AXIS_DEBUG) && !defined(LEGION)
+#define NXGE_REG_RD64(handle, offset, val_p) {\
+ int n; \
+ for (n = 0; n < AXIS_WAIT_LOOP; n++) { \
+ *(val_p) = 0; \
+ *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\
+ if (*(val_p) != (~0)) { \
+ break; \
+ } \
+ drv_usecwait(AXIS_WAIT_PER_LOOP); \
+ if (n < 20) { \
+ cmn_err(CE_WARN, "NXGE_REG_RD64: loop %d " \
+ "REG 0x%x(0x%llx)", \
+ n, offset, *val_p);\
+ } \
+ } \
+ if (n >= AXIS_WAIT_LOOP) { \
+ cmn_err(CE_WARN, "(FATAL)NXGE_REG_RD64 on offset 0x%x " \
+ "with -1!!!", offset); \
+ } \
+}
+#else
+
+#define NXGE_REG_RD64(handle, offset, val_p) {\
+ *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\
+}
+#endif
+
+/*
+ * In COSIM mode, we could loop for very long time when polling
+ * for the completion of a Clause45 frame MDIO operations. Display
+ * one rtrace line for each poll can result in messy screen. Add
+ * this MACRO for no rtrace show.
+ */
+#define NXGE_REG_RD64_NO_SHOW(handle, offset, val_p) {\
+ *(val_p) = NXGE_NPI_PIO_READ64(handle, offset);\
+}
+
+
+#if defined(REG_TRACE)
+#define NXGE_REG_WR64(handle, offset, val) {\
+ NXGE_NPI_PIO_WRITE64(handle, (offset), (val));\
+ npi_rtrace_update(handle, B_TRUE, &npi_rtracebuf, (uint32_t)offset,\
+ (uint64_t)(val));\
+}
+#elif defined(REG_SHOW)
+/*
+ * Send 0xbadbad to tell rs_show_reg that we do not have
+ * a valid RTBUF index to pass
+ */
+#define NXGE_REG_WR64(handle, offset, val) {\
+ NXGE_NPI_PIO_WRITE64(handle, offset, (val));\
+ rt_show_reg(0xbadbad, B_TRUE, (uint32_t)offset, (uint64_t)(val));\
+}
+#else
+#define NXGE_REG_WR64(handle, offset, val) {\
+ NXGE_NPI_PIO_WRITE64(handle, (offset), (val));\
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_COMMON_IMPL_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_defs.h b/usr/src/uts/sun4v/sys/nxge/nxge_defs.h
new file mode 100644
index 0000000000..60d4b26965
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_defs.h
@@ -0,0 +1,465 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_DEFS_H
+#define _SYS_NXGE_NXGE_DEFS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Block Address Assignment (24-bit base address)
+ * (bits [23:20]: block [19]: set to 1 for FZC )
+ */
+#define PIO 0x000000
+#define FZC_PIO 0x080000
+#define RESERVED_1 0x100000
+#define FZC_MAC 0x180000
+#define RESERVED_2 0x200000
+#define FZC_IPP 0x280000
+#define FFLP 0x300000
+#define FZC_FFLP 0x380000
+#define PIO_VADDR 0x400000
+#define RESERVED_3 0x480000
+#define ZCP 0x500000
+#define FZC_ZCP 0x580000
+#define DMC 0x600000
+#define FZC_DMC 0x680000
+#define TXC 0x700000
+#define FZC_TXC 0x780000
+#define PIO_LDSV 0x800000
+#define RESERVED_4 0x880000
+#define PIO_LDGIM 0x900000
+#define RESERVED_5 0x980000
+#define PIO_IMASK0 0xa00000
+#define RESERVED_6 0xa80000
+#define PIO_IMASK1 0xb00000
+#define RESERVED_7_START 0xb80000
+#define RESERVED_7_END 0xc00000
+#define FZC_PROM 0xc80000
+#define RESERVED_8 0xd00000
+#define FZC_PIM 0xd80000
+#define RESERVED_9_START 0xe00000
+#define RESERVED_9_END 0xf80000
+
+/* PIO (0x000000) */
+
+
+/* FZC_PIO (0x080000) */
+#define LDGITMRES (FZC_PIO + 0x00008) /* timer resolution */
+#define SID (FZC_PIO + 0x10200) /* 64 LDG, INT data */
+#define LDG_NUM (FZC_PIO + 0x20000) /* 69 LDs */
+
+
+
+/* FZC_IPP (0x280000) */
+
+
+/* FFLP (0x300000), Header Parser */
+
+/* PIO_VADDR (0x400000), PIO Virtaul DMA Address */
+/* ?? how to access DMA via PIO_VADDR? */
+#define VADDR (PIO_VADDR + 0x00000) /* ?? not for driver */
+
+
+/* ZCP (0x500000), Neptune Only */
+
+
+/* FZC_ZCP (0x580000), Neptune Only */
+
+
+/* DMC (0x600000), register offset (32 DMA channels) */
+
+/* Transmit Ring Register Offset (32 Channels) */
+#define TX_RNG_CFIG (DMC + 0x40000)
+#define TX_RING_HDH (DMC + 0x40008)
+#define TX_RING_HDL (DMC + 0x40010)
+#define TX_RING_KICK (DMC + 0x40018)
+/* Transmit Operations (32 Channels) */
+#define TX_ENT_MSK (DMC + 0x40020)
+#define TX_CS (DMC + 0x40028)
+#define TXDMA_MBH (DMC + 0x40030)
+#define TXDMA_MBL (DMC + 0x40038)
+#define TX_DMA_PRE_ST (DMC + 0x40040)
+#define TX_RNG_ERR_LOGH (DMC + 0x40048)
+#define TX_RNG_ERR_LOGL (DMC + 0x40050)
+#if OLD
+#define SH_TX_RNG_ERR_LOGH (DMC + 0x40058)
+#define SH_TX_RNG_ERR_LOGL (DMC + 0x40060)
+#endif
+
+/* FZC_DMC RED Initial Random Value register offset (global) */
+#define RED_RAN_INIT (FZC_DMC + 0x00068)
+
+#define RX_ADDR_MD (FZC_DMC + 0x00070)
+
+/* FZC_DMC Ethernet Timeout Countue register offset (global) */
+#define EING_TIMEOUT (FZC_DMC + 0x00078)
+
+/* RDC Table */
+#define RDC_TBL (FZC_DMC + 0x10000) /* 256 * 8 */
+
+/* FZC_DMC partitioning support register offset (32 channels) */
+
+#define TX_LOG_PAGE_VLD (FZC_DMC + 0x40000)
+#define TX_LOG_MASK1 (FZC_DMC + 0x40008)
+#define TX_LOG_VAL1 (FZC_DMC + 0x40010)
+#define TX_LOG_MASK2 (FZC_DMC + 0x40018)
+#define TX_LOG_VAL2 (FZC_DMC + 0x40020)
+#define TX_LOG_PAGE_RELO1 (FZC_DMC + 0x40028)
+#define TX_LOG_PAGE_RELO2 (FZC_DMC + 0x40030)
+#define TX_LOG_PAGE_HDL (FZC_DMC + 0x40038)
+
+#define TX_ADDR_MOD (FZC_DMC + 0x41000) /* only one? */
+
+
+/* FZC_DMC RED Parameters register offset (32 channels) */
+#define RDC_RED_PARA1 (FZC_DMC + 0x30000)
+#define RDC_RED_PARA2 (FZC_DMC + 0x30008)
+/* FZC_DMC RED Discard Cound Register offset (32 channels) */
+#define RED_DIS_CNT (FZC_DMC + 0x30010)
+
+#if OLD /* This has been moved to TXC */
+/* Transmit Ring Scheduler (per port) */
+#define TX_DMA_MAP0 (FZC_DMC + 0x50000)
+#define TX_DMA_MAP1 (FZC_DMC + 0x50008)
+#define TX_DMA_MAP2 (FZC_DMC + 0x50010)
+#define TX_DMA_MAP3 (FZC_DMC + 0x50018)
+#endif
+
+/* Transmit Ring Scheduler: DRR Weight (32 Channels) */
+#define DRR_WT (FZC_DMC + 0x51000)
+#if OLD
+#define TXRNG_USE (FZC_DMC + 0x51008)
+#endif
+
+/* TXC (0x700000)?? */
+
+
+/* FZC_TXC (0x780000)?? */
+
+
+/*
+ * PIO_LDSV (0x800000)
+ * Logical Device State Vector 0, 1, 2.
+ * (69 logical devices, 8192 apart, partitioning control)
+ */
+#define LDSV0 (PIO_LDSV + 0x00000) /* RO (64 - 69) */
+#define LDSV1 (PIO_LDSV + 0x00008) /* RO (32 - 63) */
+#define LDSV2 (PIO_LDSV + 0x00010) /* RO ( 0 - 31) */
+
+/*
+ * PIO_LDGIM (0x900000)
+ * Logical Device Group Interrupt Management (64 groups).
+ * (count 64, step 8192)
+ */
+#define LDGIMGN (PIO_LDGIMGN + 0x00000) /* RW */
+
+/*
+ * PIO_IMASK0 (0xA000000)
+ *
+ * Logical Device Masks 0, 1.
+ * (64 logical devices, 8192 apart, partitioning control)
+ */
+#define LD_IM0 (PIO_IMASK0 + 0x00000) /* RW ( 0 - 63) */
+
+/*
+ * PIO_IMASK0 (0xB000000)
+ *
+ * Logical Device Masks 0, 1.
+ * (5 logical devices, 8192 apart, partitioning control)
+ */
+#define LD_IM1 (PIO_IMASK1 + 0x00000) /* RW (64 - 69) */
+
+
+/* DMC/TMC CSR size */
+#define DMA_CSR_SIZE 512
+#define DMA_CSR_MIN_PAGE_SIZE 1024
+
+/*
+ * Define the Default RBR, RCR
+ */
+#define RBR_DEFAULT_MAX_BLKS 4096 /* each entry (16 blockaddr/64B) */
+#define RBR_NBLK_PER_LINE 16 /* 16 block addresses per 64 B line */
+#define RBR_DEFAULT_MAX_LEN (RBR_DEFAULT_MAX_BLKS)
+#define RBR_DEFAULT_MIN_LEN 1
+
+#define SW_OFFSET_NO_OFFSET 0
+#define SW_OFFSET_64 1 /* 64 bytes */
+#define SW_OFFSET_128 2 /* 128 bytes */
+#define SW_OFFSET_INVALID 3
+
+/*
+ * RBR block descriptor is 32 bits (bits [43:12]
+ */
+#define RBR_BKADDR_SHIFT 12
+
+
+#define RCR_DEFAULT_MAX_BLKS 4096 /* each entry (8 blockaddr/64B) */
+#define RCR_NBLK_PER_LINE 8 /* 8 block addresses per 64 B line */
+#define RCR_DEFAULT_MAX_LEN (RCR_DEFAULT_MAX_BLKS)
+#define RCR_DEFAULT_MIN_LEN 1
+
+/* DMA Channels. */
+#define NXGE_MAX_DMCS (NXGE_MAX_RDCS + NXGE_MAX_TDCS)
+#define NXGE_MAX_RDCS 16
+#define NXGE_MAX_TDCS 24
+#define NXGE_MAX_TDCS_NIU 16
+/*
+ * original mapping from Hypervisor
+ */
+#ifdef ORIGINAL
+#define NXGE_N2_RXDMA_START_LDG 0
+#define NXGE_N2_TXDMA_START_LDG 16
+#define NXGE_N2_MIF_LDG 32
+#define NXGE_N2_MAC_0_LDG 33
+#define NXGE_N2_MAC_1_LDG 34
+#define NXGE_N2_SYS_ERROR_LDG 35
+#endif
+
+#define NXGE_N2_RXDMA_START_LDG 19
+#define NXGE_N2_TXDMA_START_LDG 27
+#define NXGE_N2_MIF_LDG 17
+#define NXGE_N2_MAC_0_LDG 16
+#define NXGE_N2_MAC_1_LDG 35
+#define NXGE_N2_SYS_ERROR_LDG 18
+#define NXGE_N2_LDG_GAP 17
+
+#define NXGE_MAX_RDC_GRPS 8
+
+/*
+ * Max. ports per Neptune and NIU
+ */
+#define NXGE_MAX_PORTS 4
+#define NXGE_PORTS_NEPTUNE 4
+#define NXGE_PORTS_NIU 2
+
+/* Max. RDC table groups */
+#define NXGE_MAX_RDC_GROUPS 8
+#define NXGE_MAX_RDCS 16
+#define NXGE_MAX_DMAS 32
+
+
+#define NXGE_MAX_MACS_XMACS 16
+#define NXGE_MAX_MACS_BMACS 8
+#define NXGE_MAX_MACS (NXGE_MAX_PORTS * NXGE_MAX_MACS_XMACS)
+
+#define NXGE_MAX_VLANS 4096
+#define VLAN_ETHERTYPE (0x8100)
+
+
+/* Scaling factor for RBR (receive block ring) */
+#define RBR_SCALE_1 0
+#define RBR_SCALE_2 1
+#define RBR_SCALE_3 2
+#define RBR_SCALE_4 3
+#define RBR_SCALE_5 4
+#define RBR_SCALE_6 5
+#define RBR_SCALE_7 6
+#define RBR_SCALE_8 7
+
+
+#define MAX_PORTS_PER_NXGE 4
+#define MAX_MACS 32
+
+#define TX_GATHER_POINTER_SZ 8
+#define TX_GP_PER_BLOCK 8
+#define TX_DEFAULT_MAX_GPS 1024 /* Max. # of gather pointers */
+#define TX_DEFAULT_JUMBO_MAX_GPS 4096 /* Max. # of gather pointers */
+#define TX_DEFAULT_MAX_LEN (TX_DEFAULT_MAX_GPS/TX_GP_PER_BLOCK)
+#define TX_DEFAULT_JUMBO_MAX_LEN (TX_DEFAULT_JUMBO_MAX_GPS/TX_GP_PER_BLOCK)
+
+#define TX_RING_THRESHOLD (TX_DEFAULT_MAX_GPS/4)
+#define TX_RING_JUMBO_THRESHOLD (TX_DEFAULT_JUMBO_MAX_GPS/4)
+
+#define TRANSMIT_HEADER_SIZE 16 /* 16 B frame header */
+
+#define TX_DESC_SAD_SHIFT 0
+#define TX_DESC_SAD_MASK 0x00000FFFFFFFFFFFULL /* start address */
+#define TX_DESC_TR_LEN_SHIFT 44
+#define TX_DESC_TR_LEN_MASK 0x00FFF00000000000ULL /* Transfer Length */
+#define TX_DESC_NUM_PTR_SHIFT 58
+#define TX_DESC_NUM_PTR_MASK 0x2C00000000000000ULL /* gather pointers */
+#define TX_DESC_MASK_SHIFT 62
+#define TX_DESC_MASK_MASK 0x4000000000000000ULL /* Mark bit */
+#define TX_DESC_SOP_SHIF 63
+#define TX_DESC_NUM_MASK 0x8000000000000000ULL /* Start of packet */
+
+#define TCAM_FLOW_KEY_MAX_CLASS 12
+#define TCAM_L3_MAX_USER_CLASS 4
+#define TCAM_NIU_TCAM_MAX_ENTRY 128
+#define TCAM_NXGE_TCAM_MAX_ENTRY 256
+
+
+
+/* TCAM entry formats */
+#define TCAM_IPV4_5TUPLE_FORMAT 0x00
+#define TCAM_IPV6_5TUPLE_FORMAT 0x01
+#define TCAM_ETHERTYPE_FORMAT 0x02
+
+
+/* TCAM */
+#define TCAM_SELECT_IPV6 0x01
+#define TCAM_LOOKUP 0x04
+#define TCAM_DISCARD 0x08
+
+/* FLOW Key */
+#define FLOW_L4_1_34_BYTES 0x10
+#define FLOW_L4_1_78_BYTES 0x11
+#define FLOW_L4_0_12_BYTES (0x10 << 2)
+#define FLOW_L4_0_56_BYTES (0x11 << 2)
+#define FLOW_PROTO_NEXT 0x10
+#define FLOW_IPDA 0x20
+#define FLOW_IPSA 0x40
+#define FLOW_VLAN 0x80
+#define FLOW_L2DA 0x100
+#define FLOW_PORT 0x200
+
+/* TCAM */
+#define MAX_EFRAME 11
+
+#define TCAM_USE_L2RDC_FLOW_LOOKUP 0x00
+#define TCAM_USE_OFFSET_DONE 0x01
+#define TCAM_OVERRIDE_L2_FLOW_LOOKUP 0x02
+#define TCAM_OVERRIDE_L2_USE_OFFSET 0x03
+
+/*
+ * FCRAM (Hashing):
+ * 1. IPv4 exact match
+ * 2. IPv6 exact match
+ * 3. IPv4 Optimistic match
+ * 4. IPv6 Optimistic match
+ *
+ */
+#define FCRAM_IPV4_EXT_MATCH 0x00
+#define FCRAM_IPV6_EXT_MATCH 0x01
+#define FCRAM_IPV4_OPTI_MATCH 0x02
+#define FCRAM_IPV6_OPTI_MATCH 0x03
+
+
+#define NXGE_HASH_MAX_ENTRY 256
+
+
+#define MAC_ADDR_LENGTH 6
+
+/* convert values */
+#define NXGE_BASE(x, y) (((y) << (x ## _SHIFT)) & (x ## _MASK))
+#define NXGE_VAL(x, y) (((y) & (x ## _MASK)) >> (x ## _SHIFT))
+
+/*
+ * Locate the DMA channel start offset (PIO_VADDR)
+ * (DMA virtual address space of the PIO block)
+ */
+#define TDMC_PIOVADDR_OFFSET(channel) (2 * DMA_CSR_SIZE * channel)
+#define RDMC_PIOVADDR_OFFSET(channel) (TDMC_OFFSET(channel) + DMA_CSR_SIZE)
+
+/*
+ * PIO access using the DMC block directly (DMC)
+ */
+#define DMC_OFFSET(channel) (DMA_CSR_SIZE * channel)
+#define TDMC_OFFSET(channel) (TX_RNG_CFIG + DMA_CSR_SIZE * channel)
+
+/*
+ * Number of logical pages.
+ */
+#define NXGE_MAX_LOGICAL_PAGES 2
+
+#ifdef SOLARIS
+#ifndef i386
+#define _BIT_FIELDS_BIG_ENDIAN _BIT_FIELDS_HTOL
+#else
+#define _BIT_FIELDS_LITTLE_ENDIAN _BIT_FIELDS_LTOH
+#endif
+#else
+#define _BIT_FIELDS_LITTLE_ENDIAN _LITTLE_ENDIAN_BITFIELD
+#endif
+
+#ifdef COSIM
+#define MAX_PIO_RETRIES 3200
+#else
+#define MAX_PIO_RETRIES 32
+#endif
+
+#define IS_PORT_NUM_VALID(portn)\
+ (portn < 4)
+
+/*
+ * The following macros expect unsigned input values.
+ */
+#define TXDMA_CHANNEL_VALID(cn) (cn < NXGE_MAX_TDCS)
+#define TXDMA_PAGE_VALID(pn) (pn < NXGE_MAX_LOGICAL_PAGES)
+#define TXDMA_FUNC_VALID(fn) (fn < MAX_PORTS_PER_NXGE)
+#define FUNC_VALID(n) (n < MAX_PORTS_PER_NXGE)
+
+/*
+ * DMA channel binding definitions.
+ */
+#define VIR_PAGE_INDEX_MAX 8
+#define VIR_SUB_REGIONS 2
+#define VIR_DMA_BIND 1
+
+#define SUBREGION_VALID(n) (n < VIR_SUB_REGIONS)
+#define VIR_PAGE_INDEX_VALID(n) (n < VIR_PAGE_INDEX_MAX)
+#define VRXDMA_CHANNEL_VALID(n) (n < NXGE_MAX_RDCS)
+
+/*
+ * Logical device definitions.
+ */
+#define NXGE_INT_MAX_LD 69
+#define NXGE_INT_MAX_LDG 64
+
+#define NXGE_RDMA_LD_START 0
+#define NXGE_TDMA_LD_START 32
+#define NXGE_MIF_LD 63
+#define NXGE_MAC_LD_PORT0 64
+#define NXGE_MAC_LD_PORT1 65
+#define NXGE_MAC_LD_PORT2 66
+#define NXGE_MAC_LD_PORT3 67
+#define NXGE_SYS_ERROR_LD 68
+
+#define LDG_VALID(n) (n < NXGE_INT_MAX_LDG)
+#define LD_VALID(n) (n < NXGE_INT_MAX_LD)
+#define LD_RXDMA_LD_VALID(n) (n < NXGE_MAX_RDCS)
+#define LD_TXDMA_LD_VALID(n) (n >= NXGE_MAX_RDCS && \
+ ((n - NXGE_MAX_RDCS) < NXGE_MAX_TDCS)))
+#define LD_MAC_VALID(n) (IS_PORT_NUM_VALID(n))
+
+#define LD_TIMER_MAX 0x3f
+#define LD_INTTIMER_VALID(n) (n <= LD_TIMER_MAX)
+
+/* System Interrupt Data */
+#define SID_VECTOR_MAX 0x1f
+#define SID_VECTOR_VALID(n) (n <= SID_VECTOR_MAX)
+
+#define NXGE_COMPILE_32
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_DEFS_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_espc.h b/usr/src/uts/sun4v/sys/nxge/nxge_espc.h
new file mode 100644
index 0000000000..b54fec9d6d
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_espc.h
@@ -0,0 +1,236 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_ESPC_H
+#define _SYS_NXGE_NXGE_ESPC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_espc_hw.h>
+
+#define ESPC_MAC_ADDR_0 ESPC_NCR_REGN(0)
+#define ESPC_MAC_ADDR_1 ESPC_NCR_REGN(1)
+#define ESPC_NUM_PORTS_MACS ESPC_NCR_REGN(2)
+#define ESPC_MOD_STR_LEN ESPC_NCR_REGN(4)
+#define ESPC_MOD_STR_1 ESPC_NCR_REGN(5)
+#define ESPC_MOD_STR_2 ESPC_NCR_REGN(6)
+#define ESPC_MOD_STR_3 ESPC_NCR_REGN(7)
+#define ESPC_MOD_STR_4 ESPC_NCR_REGN(8)
+#define ESPC_MOD_STR_5 ESPC_NCR_REGN(9)
+#define ESPC_MOD_STR_6 ESPC_NCR_REGN(10)
+#define ESPC_MOD_STR_7 ESPC_NCR_REGN(11)
+#define ESPC_MOD_STR_8 ESPC_NCR_REGN(12)
+#define ESPC_BD_MOD_STR_LEN ESPC_NCR_REGN(13)
+#define ESPC_BD_MOD_STR_1 ESPC_NCR_REGN(14)
+#define ESPC_BD_MOD_STR_2 ESPC_NCR_REGN(15)
+#define ESPC_BD_MOD_STR_3 ESPC_NCR_REGN(16)
+#define ESPC_BD_MOD_STR_4 ESPC_NCR_REGN(17)
+#define ESPC_PHY_TYPE ESPC_NCR_REGN(18)
+#define ESPC_MAX_FM_SZ ESPC_NCR_REGN(19)
+#define ESPC_INTR_NUM ESPC_NCR_REGN(20)
+#define ESPC_VER_IMGSZ ESPC_NCR_REGN(21)
+#define ESPC_CHKSUM ESPC_NCR_REGN(22)
+
+#define NUM_PORTS_MASK 0xff
+#define NUM_MAC_ADDRS_MASK 0xff0000
+#define NUM_MAC_ADDRS_SHIFT 16
+#define MOD_STR_LEN_MASK 0xffff
+#define BD_MOD_STR_LEN_MASK 0xffff
+#define MAX_FM_SZ_MASK 0xffff
+#define VER_NUM_MASK 0xffff
+#define IMG_SZ_MASK 0xffff0000
+#define IMG_SZ_SHIFT 16
+#define CHKSUM_MASK 0xff
+
+/* 0 <= n < 8 */
+#define ESPC_MOD_STR(n) (ESPC_MOD_STR_1 + n*8)
+#define MAX_MOD_STR_LEN 32
+
+/* 0 <= n < 4 */
+#define ESPC_BD_MOD_STR(n) (ESPC_BD_MOD_STR_1 + n*8)
+#define MAX_BD_MOD_STR_LEN 16
+
+#define ESC_PHY_10G_FIBER 0x0
+#define ESC_PHY_10G_COPPER 0x1
+#define ESC_PHY_1G_FIBER 0x2
+#define ESC_PHY_1G_COPPER 0x3
+#define ESC_PHY_NONE 0xf
+
+#define ESC_IMG_CHKSUM_VAL 0xab
+
+typedef union _mac_addr_0_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t byte3 : 8;
+ uint32_t byte2 : 8;
+ uint32_t byte1 : 8;
+ uint32_t byte0 : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t byte0 : 8;
+ uint32_t byte1 : 8;
+ uint32_t byte2 : 8;
+ uint32_t byte3 : 8;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mac_addr_0_t;
+
+typedef union _mac_addr_1_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res : 16;
+ uint32_t byte5 : 8;
+ uint32_t byte4 : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t byte4 : 8;
+ uint32_t byte5 : 8;
+ uint32_t res : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mac_addr_1_t;
+
+
+typedef union _phy_type_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pt0_phy_type : 8;
+ uint32_t pt1_phy_type : 8;
+ uint32_t pt2_phy_type : 8;
+ uint32_t pt3_phy_type : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pt3_phy_type : 8;
+ uint32_t pt2_phy_type : 8;
+ uint32_t pt1_phy_type : 8;
+ uint32_t pt0_phy_type : 8;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} phy_type_t;
+
+
+typedef union _intr_num_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pt0_intr_num : 8;
+ uint32_t pt1_intr_num : 8;
+ uint32_t pt2_intr_num : 8;
+ uint32_t pt3_intr_num : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pt3_intr_num : 8;
+ uint32_t pt2_intr_num : 8;
+ uint32_t pt1_intr_num : 8;
+ uint32_t pt0_intr_num : 8;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} intr_num_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_ESPC_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_espc_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_espc_hw.h
new file mode 100644
index 0000000000..e38dda43bb
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_espc_hw.h
@@ -0,0 +1,64 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_ESPC_HW_H
+#define _SYS_NXGE_NXGE_ESPC_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+/* EPC / SPC Registers offsets */
+#define ESPC_PIO_EN_REG 0x040000
+#define ESPC_PIO_EN_MASK 0x0000000000000001ULL
+#define ESPC_PIO_STATUS_REG 0x040008
+
+/* EPC Status Register */
+#define EPC_READ_INITIATE (1ULL << 31)
+#define EPC_READ_COMPLETE (1 << 30)
+#define EPC_WRITE_INITIATE (1 << 29)
+#define EPC_WRITE_COMPLETE (1 << 28)
+#define EPC_EEPROM_ADDR_BITS 0x3FFFF
+#define EPC_EEPROM_ADDR_SHIFT 8
+#define EPC_EEPROM_ADDR_MASK (EPC_EEPROM_ADDR_BITS << EPC_EEPROM_ADDR_SHIFT)
+#define EPC_EEPROM_DATA_MASK 0xFF
+
+#define EPC_RW_WAIT 10 /* TBD */
+
+#define ESPC_NCR_REG 0x040020 /* Count 128, step 8 */
+#define ESPC_REG_ADDR(reg) (FZC_PROM + (reg))
+
+#define ESPC_NCR_REGN(n) ((ESPC_REG_ADDR(ESPC_NCR_REG)) + n*8)
+#define ESPC_NCR_VAL_MASK 0x00000000FFFFFFFFULL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_ESPC_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_fflp.h b/usr/src/uts/sun4v/sys/nxge/nxge_fflp.h
new file mode 100644
index 0000000000..93458357a6
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_fflp.h
@@ -0,0 +1,233 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_FFLP_H
+#define _SYS_NXGE_NXGE_FFLP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi_fflp.h>
+
+#define MAX_PARTITION 8
+
+typedef struct _fflp_errlog {
+ uint32_t vlan;
+ uint32_t tcam;
+ uint32_t hash_pio[MAX_PARTITION];
+ uint32_t hash_lookup1;
+ uint32_t hash_lookup2;
+} fflp_errlog_t, *p_fflp_errlog_t;
+
+typedef struct _fflp_stats {
+ uint32_t tcam_entries;
+ uint32_t fcram_entries;
+ uint32_t tcam_parity_err;
+ uint32_t tcam_ecc_err;
+ uint32_t vlan_parity_err;
+ uint32_t hash_lookup_err;
+ uint32_t hash_pio_err[MAX_PARTITION];
+ fflp_errlog_t errlog;
+} nxge_fflp_stats_t, *p_nxge_fflp_stats_t;
+
+/*
+ * The FCRAM (hash table) cosnists of 1 meg cells
+ * each 64 byte wide. Each cell can hold either of:
+ * 2 IPV4 Exact match entry (each 32 bytes)
+ * 1 IPV6 Exact match entry (each 56 bytes) and
+ * 1 Optimistic match entry (each 8 bytes)
+ * 8 Optimistic match entries (each 8 bytes)
+ * In the case IPV4 Exact match, half of the cell
+ * (the first or the second 32 bytes) could be used
+ * to hold 4 Optimistic matches
+ */
+
+#define FCRAM_CELL_EMPTY 0x00
+#define FCRAM_CELL_IPV4_IPV4 0x01
+#define FCRAM_CELL_IPV4_OPT 0x02
+#define FCRAM_CELL_OPT_IPV4 0x04
+#define FCRAM_CELL_IPV6_OPT 0x08
+#define FCRAM_CELL_OPT_OPT 0x10
+
+
+#define FCRAM_SUBAREA0_OCCUPIED 0x01
+#define FCRAM_SUBAREA1_OCCUPIED 0x02
+#define FCRAM_SUBAREA2_OCCUPIED 0x04
+#define FCRAM_SUBAREA3_OCCUPIED 0x08
+
+#define FCRAM_SUBAREA4_OCCUPIED 0x10
+#define FCRAM_SUBAREA5_OCCUPIED 0x20
+#define FCRAM_SUBAREA6_OCCUPIED 0x40
+#define FCRAM_SUBAREA7_OCCUPIED 0x20
+
+#define FCRAM_IPV4_SUBAREA0_OCCUPIED \
+ (FCRAM_SUBAREA0_OCCUPIED | FCRAM_SUBAREA1_OCCUPIED | \
+ FCRAM_SUBAREA2_OCCUPIED | FCRAM_SUBAREA3_OCCUPIED)
+
+#define FCRAM_IPV4_SUBAREA4_OCCUPIED \
+ (FCRAM_SUBAREA4_OCCUPIED | FCRAM_SUBAREA5_OCCUPIED | \
+ FCRAM_SUBAREA6_OCCUPIED | FCRAM_SUBAREA7_OCCUPIED)
+
+
+#define FCRAM_IPV6_SUBAREA0_OCCUPIED \
+ (FCRAM_SUBAREA0_OCCUPIED | FCRAM_SUBAREA1_OCCUPIED | \
+ FCRAM_SUBAREA2_OCCUPIED | FCRAM_SUBAREA3_OCCUPIED | \
+ FCRAM_SUBAREA4_OCCUPIED | FCRAM_SUBAREA5_OCCUPIED | \
+ FCRAM_SUBAREA6_OCCUPIED)
+
+ /*
+ * The current occupancy state of each FCRAM cell isy
+ * described by the fcram_cell_t data structure.
+ * The "type" field denotes the type of entry (or combination)
+ * the cell holds (FCRAM_CELL_EMPTY ...... FCRAM_CELL_OPT_OPT)
+ * The "occupied" field indicates if individual 8 bytes (subareas)
+ * with in the cell are occupied
+ */
+
+typedef struct _fcram_cell {
+ uint32_t type:8;
+ uint32_t occupied:8;
+ uint32_t shadow_loc:16;
+} fcram_cell_t, *p_fcram_cell_t;
+
+typedef struct _fcram_parition {
+ uint8_t id;
+ uint8_t base;
+ uint8_t mask;
+ uint8_t reloc;
+ uint32_t flags;
+#define HASH_PARTITION_ENABLED 1
+ uint32_t offset;
+ uint32_t size;
+} fcram_parition_t, *p_fcram_partition_t;
+
+
+typedef struct _tcam_flow_spec {
+ tcam_entry_t tce;
+ uint64_t flags;
+ uint64_t user_info;
+} tcam_flow_spec_t, *p_tcam_flow_spec_t;
+
+
+/*
+ * Used for configuration.
+ * ndd as well nxge.conf use the following definitions
+ */
+
+#define NXGE_CLASS_CONFIG_PARAMS 20
+/* Used for ip class flow key and tcam key config */
+
+#define NXGE_CLASS_TCAM_LOOKUP 0x0001
+#define NXGE_CLASS_TCAM_USE_SRC_ADDR 0x0002
+#define NXGE_CLASS_FLOW_USE_PORTNUM 0x0010
+#define NXGE_CLASS_FLOW_USE_L2DA 0x0020
+#define NXGE_CLASS_FLOW_USE_VLAN 0x0040
+#define NXGE_CLASS_FLOW_USE_PROTO 0x0080
+#define NXGE_CLASS_FLOW_USE_IPSRC 0x0100
+#define NXGE_CLASS_FLOW_USE_IPDST 0x0200
+#define NXGE_CLASS_FLOW_USE_SRC_PORT 0x0400
+#define NXGE_CLASS_FLOW_USE_DST_PORT 0x0800
+#define NXGE_CLASS_DISCARD 0x80000000
+
+/* these are used for quick configs */
+#define NXGE_CLASS_FLOW_WEB_SERVER NXGE_CLASS_FLOW_USE_IPSRC | \
+ NXGE_CLASS_FLOW_USE_SRC_PORT
+
+#define NXGE_CLASS_FLOW_GEN_SERVER NXGE_CLASS_FLOW_USE_IPSRC | \
+ NXGE_CLASS_FLOW_USE_IPDST | \
+ NXGE_CLASS_FLOW_USE_SRC_PORT | \
+ NXGE_CLASS_FLOW_USE_DST_PORT | \
+ NXGE_CLASS_FLOW_USE_PROTO | \
+ NXGE_CLASS_FLOW_USE_L2DA | \
+ NXGE_CLASS_FLOW_USE_VLAN
+
+/*
+ * used for use classes
+ */
+
+
+/* Ethernet Classes */
+#define NXGE_CLASS_CFG_ETHER_TYPE_MASK 0x0000FFFF
+#define NXGE_CLASS_CFG_ETHER_ENABLE_MASK 0x40000000
+
+/* IP Classes */
+#define NXGE_CLASS_CFG_IP_TOS_MASK 0x000000FF
+#define NXGE_CLASS_CFG_IP_TOS_SHIFT 0
+#define NXGE_CLASS_CFG_IP_TOS_MASK_MASK 0x0000FF00
+#define NXGE_CLASS_CFG_IP_TOS_MASK_SHIFT 8
+#define NXGE_CLASS_CFG_IP_PROTO_MASK 0x00FFFF00
+#define NXGE_CLASS_CFG_IP_PROTO_SHIFT 16
+
+#define NXGE_CLASS_CFG_IP_IPV6_MASK 0x01000000
+#define NXGE_CLASS_CFG_IP_PARAM_MASK NXGE_CLASS_CFG_IP_TOS_MASK | \
+ NXGE_CLASS_CFG_IP_TOS_MASK_MASK | \
+ NXGE_CLASS_CFG_IP_PROTO_MASK | \
+ NXGE_CLASS_CFG_IP_IPV6_MASK
+
+#define NXGE_CLASS_CFG_IP_ENABLE_MASK 0x40000000
+
+typedef struct _vlan_rdcgrp_map {
+ uint32_t rsrvd:8;
+ uint32_t vid:16;
+ uint32_t rdc_grp:8;
+} vlan_rdcgrp_map_t, *p_vlan_rdcgrp_map_t;
+
+#define NXGE_INIT_VLAN_RDCG_TBL 32
+
+typedef struct _nxge_classify {
+ nxge_os_mutex_t tcam_lock;
+ nxge_os_mutex_t fcram_lock;
+ nxge_os_mutex_t hash_lock[MAX_PARTITION];
+ uint32_t tcam_size;
+ uint32_t state;
+#define NXGE_FFLP_HW_RESET 0x1
+#define NXGE_FFLP_HW_INIT 0x2
+#define NXGE_FFLP_SW_INIT 0x4
+#define NXGE_FFLP_FCRAM_PART 0x80000000
+ p_nxge_fflp_stats_t fflp_stats;
+
+ tcam_flow_spec_t *tcam_entries;
+ uint8_t tcam_location;
+#define NXGE_FLOW_NO_SUPPORT 0x0
+#define NXGE_FLOW_USE_TCAM 0x1
+#define NXGE_FLOW_USE_FCRAM 0x2
+#define NXGE_FLOW_USE_TCAM_FCRAM 0x3
+
+#define NXGE_FLOW_COMPUTE_H1 0x10
+#define NXGE_FLOW_COMPUTE_H2 0x20
+ uint8_t fragment_bug;
+ uint8_t fragment_bug_location;
+ fcram_cell_t *hash_table; /* allocated for Neptune only */
+ fcram_parition_t partition[MAX_PARTITION];
+} nxge_classify_t, *p_nxge_classify_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_FFLP_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hash.h b/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hash.h
new file mode 100644
index 0000000000..74e42d7e3f
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hash.h
@@ -0,0 +1,58 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_CRC_H
+#define _SYS_NXGE_NXGE_CRC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void nxge_crc32c_init(void);
+uint32_t nxge_crc32c(uint32_t, const uint8_t *, int);
+
+void nxge_crc_ccitt_init(void);
+uint16_t nxge_crc_ccitt(uint16_t, const uint8_t *, int);
+
+uint32_t nxge_compute_h1_table1(uint32_t, uint32_t *, uint32_t);
+uint32_t nxge_compute_h1_table4(uint32_t, uint32_t *, uint32_t);
+uint32_t nxge_compute_h1_serial(uint32_t crcin, uint32_t *, uint32_t);
+
+#define nxge_compute_h2(cin, flow, len) \
+ nxge_crc_ccitt(cin, flow, len)
+
+void nxge_init_h1_table(void);
+
+#define nxge_compute_h1(cin, flow, len) \
+ nxge_compute_h1_table4(cin, flow, len)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_CRC_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hw.h
new file mode 100644
index 0000000000..a2d550da5b
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_fflp_hw.h
@@ -0,0 +1,1668 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_FFLP_HW_H
+#define _SYS_NXGE_NXGE_FFLP_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+
+/* FZC_FFLP Offsets */
+#define FFLP_ENET_VLAN_TBL_REG (FZC_FFLP + 0x00000)
+
+ /* defines for FFLP_ENET_VLAN_TBL */
+
+#define ENET_VLAN_TBL_VLANRDCTBLN0_MASK 0x0000000000000003ULL
+#define ENET_VLAN_TBL_VLANRDCTBLN0_SHIFT 0
+#define ENET_VLAN_TBL_VPR0_MASK 0x00000000000000008ULL
+#define ENET_VLAN_TBL_VPR0_SHIFT 3
+
+#define ENET_VLAN_TBL_VLANRDCTBLN1_MASK 0x0000000000000030ULL
+#define ENET_VLAN_TBL_VLANRDCTBLN1_SHIFT 4
+#define ENET_VLAN_TBL_VPR1_MASK 0x00000000000000080ULL
+#define ENET_VLAN_TBL_VPR1_SHIFT 7
+
+#define ENET_VLAN_TBL_VLANRDCTBLN2_MASK 0x0000000000000300ULL
+#define ENET_VLAN_TBL_VLANRDCTBLN2_SHIFT 8
+#define ENET_VLAN_TBL_VPR2_MASK 0x00000000000000800ULL
+#define ENET_VLAN_TBL_VPR2_SHIFT 11
+
+#define ENET_VLAN_TBL_VLANRDCTBLN3_MASK 0x0000000000003000ULL
+#define ENET_VLAN_TBL_VLANRDCTBLN3_SHIFT 12
+#define ENET_VLAN_TBL_VPR3_MASK 0x0000000000008000ULL
+#define ENET_VLAN_TBL_VPR3_SHIFT 15
+
+#define ENET_VLAN_TBL_PARITY0_MASK 0x0000000000010000ULL
+#define ENET_VLAN_TBL_PARITY0_SHIFT 16
+#define ENET_VLAN_TBL_PARITY1_MASK 0x0000000000020000ULL
+#define ENET_VLAN_TBL_PARITY1_SHIFT 17
+
+
+
+typedef union _fflp_enet_vlan_tbl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:14;
+ uint32_t parity1:1;
+ uint32_t parity0:1;
+ uint32_t vpr3:1;
+ uint32_t vlanrdctbln3:3;
+ uint32_t vpr2:1;
+ uint32_t vlanrdctbln2:3;
+ uint32_t vpr1:1;
+ uint32_t vlanrdctbln1:3;
+ uint32_t vpr0:1;
+ uint32_t vlanrdctbln0:3;
+#else
+ uint32_t vlanrdctbln0:3;
+ uint32_t vpr0:1;
+ uint32_t vlanrdctbln1:3;
+ uint32_t vpr1:1;
+ uint32_t vlanrdctbln2:3;
+ uint32_t vpr2:1;
+ uint32_t vlanrdctbln3:3;
+ uint32_t vpr3:1;
+ uint32_t parity0:1;
+ uint32_t parity1:1;
+ uint32_t rsrvd:14;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fflp_enet_vlan_tbl_t, *p_fflp_enet_vlan_tbl_t;
+
+
+#define FFLP_TCAM_CLS_BASE_OFFSET (FZC_FFLP + 0x20000)
+#define FFLP_L2_CLS_ENET1_REG (FZC_FFLP + 0x20000)
+#define FFLP_L2_CLS_ENET2_REG (FZC_FFLP + 0x20008)
+
+
+
+typedef union _tcam_class_prg_ether_t {
+#define TCAM_ENET_USR_CLASS_ENABLE 0x1
+#define TCAM_ENET_USR_CLASS_DISABLE 0x0
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:15;
+ uint32_t valid:1;
+ uint32_t etype:16;
+#else
+ uint32_t etype:16;
+ uint32_t valid:1;
+ uint32_t rsrvd:15;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcam_class_prg_ether_t, *p_tcam_class_prg_ether_t;
+
+
+#define FFLP_L3_CLS_IP_U4_REG (FZC_FFLP + 0x20010)
+#define FFLP_L3_CLS_IP_U5_REG (FZC_FFLP + 0x20018)
+#define FFLP_L3_CLS_IP_U6_REG (FZC_FFLP + 0x20020)
+#define FFLP_L3_CLS_IP_U7_REG (FZC_FFLP + 0x20028)
+
+typedef union _tcam_class_prg_ip_t {
+#define TCAM_IP_USR_CLASS_ENABLE 0x1
+#define TCAM_IP_USR_CLASS_DISABLE 0x0
+
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:6;
+ uint32_t valid:1;
+ uint32_t ipver:1;
+ uint32_t pid:8;
+ uint32_t tosmask:8;
+ uint32_t tos:8;
+#else
+ uint32_t tos:8;
+ uint32_t tosmask:8;
+ uint32_t pid:8;
+ uint32_t ipver:1;
+ uint32_t valid:1;
+ uint32_t rsrvd:6;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcam_class_prg_ip_t, *p_tcam_class_prg_ip_t;
+/* define the classes which use the above structure */
+
+typedef enum fflp_tcam_class {
+ TCAM_CLASS_INVALID = 0,
+ TCAM_CLASS_DUMMY = 1,
+ TCAM_CLASS_ETYPE_1 = 2,
+ TCAM_CLASS_ETYPE_2,
+ TCAM_CLASS_IP_USER_4,
+ TCAM_CLASS_IP_USER_5,
+ TCAM_CLASS_IP_USER_6,
+ TCAM_CLASS_IP_USER_7,
+ TCAM_CLASS_TCP_IPV4,
+ TCAM_CLASS_UDP_IPV4,
+ TCAM_CLASS_AH_ESP_IPV4,
+ TCAM_CLASS_SCTP_IPV4,
+ TCAM_CLASS_TCP_IPV6,
+ TCAM_CLASS_UDP_IPV6,
+ TCAM_CLASS_AH_ESP_IPV6,
+ TCAM_CLASS_SCTP_IPV6,
+ TCAM_CLASS_ARP,
+ TCAM_CLASS_RARP,
+ TCAM_CLASS_DUMMY_12,
+ TCAM_CLASS_DUMMY_13,
+ TCAM_CLASS_DUMMY_14,
+ TCAM_CLASS_DUMMY_15,
+ TCAM_CLASS_MAX
+} tcam_class_t;
+
+
+
+/*
+ * Specify how to build TCAM key for L3
+ * IP Classes. Both User configured and
+ * hardwired IP services are included.
+ * These are the supported 12 classes.
+ */
+
+#define FFLP_TCAM_KEY_BASE_OFFSET (FZC_FFLP + 0x20030)
+#define FFLP_TCAM_KEY_IP_USR4_REG (FZC_FFLP + 0x20030)
+#define FFLP_TCAM_KEY_IP_USR5_REG (FZC_FFLP + 0x20038)
+#define FFLP_TCAM_KEY_IP_USR6_REG (FZC_FFLP + 0x20040)
+#define FFLP_TCAM_KEY_IP_USR7_REG (FZC_FFLP + 0x20048)
+#define FFLP_TCAM_KEY_IP4_TCP_REG (FZC_FFLP + 0x20050)
+#define FFLP_TCAM_KEY_IP4_UDP_REG (FZC_FFLP + 0x20058)
+#define FFLP_TCAM_KEY_IP4_AH_ESP_REG (FZC_FFLP + 0x20060)
+#define FFLP_TCAM_KEY_IP4_SCTP_REG (FZC_FFLP + 0x20068)
+#define FFLP_TCAM_KEY_IP6_TCP_REG (FZC_FFLP + 0x20070)
+#define FFLP_TCAM_KEY_IP6_UDP_REG (FZC_FFLP + 0x20078)
+#define FFLP_TCAM_KEY_IP6_AH_ESP_REG (FZC_FFLP + 0x20080)
+#define FFLP_TCAM_KEY_IP6_SCTP_REG (FZC_FFLP + 0x20088)
+
+
+typedef union _tcam_class_key_ip_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd2:28;
+ uint32_t discard:1;
+ uint32_t tsel:1;
+ uint32_t rsrvd:1;
+ uint32_t ipaddr:1;
+#else
+ uint32_t ipaddr:1;
+ uint32_t rsrvd:1;
+ uint32_t tsel:1;
+ uint32_t discard:1;
+ uint32_t rsrvd2:28;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcam_class_key_ip_t, *p_tcam_class_key_ip_t;
+
+
+
+#define FFLP_TCAM_KEY_0_REG (FZC_FFLP + 0x20090)
+#define FFLP_TCAM_KEY_1_REG (FZC_FFLP + 0x20098)
+#define FFLP_TCAM_KEY_2_REG (FZC_FFLP + 0x200A0)
+#define FFLP_TCAM_KEY_3_REG (FZC_FFLP + 0x200A8)
+#define FFLP_TCAM_MASK_0_REG (FZC_FFLP + 0x200B0)
+#define FFLP_TCAM_MASK_1_REG (FZC_FFLP + 0x200B8)
+#define FFLP_TCAM_MASK_2_REG (FZC_FFLP + 0x200C0)
+#define FFLP_TCAM_MASK_3_REG (FZC_FFLP + 0x200C8)
+
+#define FFLP_TCAM_CTL_REG (FZC_FFLP + 0x200D0)
+
+/* bit defines for FFLP_TCAM_CTL register */
+#define TCAM_CTL_TCAM_WR 0x0ULL
+#define TCAM_CTL_TCAM_RD 0x040000ULL
+#define TCAM_CTL_TCAM_CMP 0x080000ULL
+#define TCAM_CTL_RAM_WR 0x100000ULL
+#define TCAM_CTL_RAM_RD 0x140000ULL
+#define TCAM_CTL_RWC_STAT 0x0020000ULL
+#define TCAM_CTL_RWC_MATCH 0x0010000ULL
+
+
+typedef union _tcam_ctl_t {
+#define TCAM_CTL_RWC_TCAM_WR 0x0
+#define TCAM_CTL_RWC_TCAM_RD 0x1
+#define TCAM_CTL_RWC_TCAM_CMP 0x2
+#define TCAM_CTL_RWC_RAM_WR 0x4
+#define TCAM_CTL_RWC_RAM_RD 0x5
+#define TCAM_CTL_RWC_RWC_STAT 0x1
+#define TCAM_CTL_RWC_RWC_MATCH 0x1
+
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd2:11;
+ uint32_t rwc:3;
+ uint32_t stat:1;
+ uint32_t match:1;
+ uint32_t rsrvd:6;
+ uint32_t location:10;
+#else
+ uint32_t location:10;
+ uint32_t rsrvd:6;
+ uint32_t match:1;
+ uint32_t stat:1;
+ uint32_t rwc:3;
+ uint32_t rsrvd2:11;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcam_ctl_t, *p_tcam_ctl_t;
+
+
+
+/* Bit defines for TCAM ASC RAM */
+
+
+typedef union _tcam_res_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+ uint32_t rsrvd:22;
+ uint32_t syndrome:10;
+ } hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t syndrome:6;
+ uint32_t zfid:12;
+ uint32_t v4_ecc_ck:1;
+ uint32_t disc:1;
+ uint32_t tres:2;
+ uint32_t rdctbl:3;
+ uint32_t offset:5;
+ uint32_t zfld:1;
+ uint32_t age:1;
+#else
+ uint32_t age:1;
+ uint32_t zfld:1;
+ uint32_t offset:5;
+ uint32_t rdctbl:3;
+ uint32_t tres:2;
+ uint32_t disc:1;
+ uint32_t v4_ecc_ck:1;
+ uint32_t zfid:12;
+ uint32_t syndrome:6;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ struct {
+ uint32_t syndrome:10;
+ uint32_t rsrvd:22;
+ } hdw;
+#endif
+ } bits;
+} tcam_res_t, *p_tcam_res_t;
+
+
+
+#define TCAM_ASC_DATA_AGE 0x0000000000000001ULL
+#define TCAM_ASC_DATA_AGE_SHIFT 0x0
+#define TCAM_ASC_DATA_ZFVLD 0x0000000000000002ULL
+#define TCAM_ASC_DATA_ZFVLD_SHIFT 1
+
+#define TCAM_ASC_DATA_OFFSET_MASK 0x000000000000007CULL
+#define TCAM_ASC_DATA_OFFSET_SHIFT 2
+
+#define TCAM_ASC_DATA_RDCTBL_MASK 0x0000000000000038ULL
+#define TCAM_ASC_DATA_RDCTBL_SHIFT 7
+#define TCAM_ASC_DATA_TRES_MASK 0x0000000000000C00ULL
+#define TRES_CONT_USE_L2RDC 0x00
+#define TRES_TERM_USE_OFFSET 0x01
+#define TRES_CONT_OVRD_L2RDC 0x02
+#define TRES_TERM_OVRD_L2RDC 0x03
+
+#define TCAM_ASC_DATA_TRES_SHIFT 10
+#define TCAM_TRES_CONT_USE_L2RDC \
+ (0x0000000000000000ULL << TCAM_ASC_DATA_TRES_SHIFT)
+#define TCAM_TRES_TERM_USE_OFFSET \
+ (0x0000000000000001ULL << TCAM_ASC_DATA_TRES_SHIFT)
+#define TCAM_TRES_CONT_OVRD_L2RDC \
+ (0x0000000000000002ULL << TCAM_ASC_DATA_TRES_SHIFT)
+#define TCAM_TRES_TERM_OVRD_L2RDC \
+ (0x0000000000000003ULL << TCAM_ASC_DATA_TRES_SHIFT)
+
+#define TCAM_ASC_DATA_DISC_MASK 0x0000000000001000ULL
+#define TCAM_ASC_DATA_DISC_SHIFT 12
+#define TCAM_ASC_DATA_V4_ECC_OK_MASK 0x0000000000002000ULL
+#define TCAM_ASC_DATA_V4_ECC_OK_SHIFT 13
+#define TCAM_ASC_DATA_V4_ECC_OK \
+ (0x0000000000000001ULL << TCAM_ASC_DATA_V4_ECC_OK_MASK_SHIFT)
+
+#define TCAM_ASC_DATA_ZFID_MASK 0x0000000003FF3000ULL
+#define TCAM_ASC_DATA_ZFID_SHIFT 14
+#define TCAM_ASC_DATA_ZFID(value) \
+ ((value & TCAM_ASC_DATA_ZFID_MASK) >> TCAM_ASC_DATA_ZFID_SHIFT)
+
+#define TCAM_ASC_DATA_SYNDR_MASK 0x000003FFF3000000ULL
+#define TCAM_ASC_DATA_SYNDR_SHIFT 26
+#define TCAM_ASC_DATA_SYNDR(value) \
+ ((value & TCAM_ASC_DATA_SYNDR_MASK) >> TCAM_ASC_DATA_SYNDR_SHIFT)
+
+
+ /* error registers */
+
+#define FFLP_VLAN_PAR_ERR_REG (FZC_FFLP + 0x08000)
+
+typedef union _vlan_par_err_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t err:1;
+ uint32_t m_err:1;
+ uint32_t addr:12;
+ uint32_t data:18;
+#else
+ uint32_t data:18;
+ uint32_t addr:12;
+ uint32_t m_err:1;
+ uint32_t err:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} vlan_par_err_t, *p_vlan_par_err_t;
+
+
+#define FFLP_TCAM_ERR_REG (FZC_FFLP + 0x200D8)
+
+typedef union _tcam_err_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t err:1;
+ uint32_t p_ecc:1;
+ uint32_t mult:1;
+ uint32_t rsrvd:5;
+ uint32_t addr:8;
+ uint32_t syndrome:16;
+#else
+ uint32_t syndrome:16;
+ uint32_t addr:8;
+ uint32_t rsrvd:5;
+ uint32_t mult:1;
+ uint32_t p_ecc:1;
+ uint32_t err:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcam_err_t, *p_tcam_err_t;
+
+
+#define TCAM_ERR_SYNDROME_MASK 0x000000000000FFFFULL
+#define TCAM_ERR_MULT_SHIFT 29
+#define TCAM_ERR_MULT 0x0000000020000000ULL
+#define TCAM_ERR_P_ECC 0x0000000040000000ULL
+#define TCAM_ERR_ERR 0x0000000080000000ULL
+
+#define HASH_LKUP_ERR_LOG1_REG (FZC_FFLP + 0x200E0)
+#define HASH_LKUP_ERR_LOG2_REG (FZC_FFLP + 0x200E8)
+
+
+
+typedef union _hash_lookup_err_log1_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:28;
+ uint32_t ecc_err:1;
+ uint32_t mult_lk:1;
+ uint32_t cu:1;
+ uint32_t mult_bit:1;
+#else
+ uint32_t mult_bit:1;
+ uint32_t cu:1;
+ uint32_t mult_lk:1;
+ uint32_t ecc_err:1;
+ uint32_t rsrvd:28;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_lookup_err_log1_t, *p_hash_lookup_err_log1_t;
+
+
+
+typedef union _hash_lookup_err_log2_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:1;
+ uint32_t h1:20;
+ uint32_t subarea:3;
+ uint32_t syndrome:8;
+#else
+ uint32_t syndrome:8;
+ uint32_t subarea:3;
+ uint32_t h1:20;
+ uint32_t rsrvd:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_lookup_err_log2_t, *p_hash_lookup_err_log2_t;
+
+
+
+#define FFLP_FCRAM_ERR_TST0_REG (FZC_FFLP + 0x20128)
+
+typedef union _fcram_err_tst0_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:24;
+ uint32_t syndrome_mask:8;
+#else
+ uint32_t syndrome_mask:10;
+ uint32_t rsrvd:24;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fcram_err_tst0_t, *p_fcram_err_tst0_t;
+
+
+#define FFLP_FCRAM_ERR_TST1_REG (FZC_FFLP + 0x20130)
+#define FFLP_FCRAM_ERR_TST2_REG (FZC_FFLP + 0x20138)
+
+typedef union _fcram_err_tst_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+ uint32_t dat;
+ } hdw;
+#endif
+ struct {
+ uint32_t dat;
+ } ldw;
+#ifndef _BIG_ENDIAN
+ struct {
+ uint32_t dat;
+ } hdw;
+#endif
+ } bits;
+} fcram_err_tst1_t, *p_fcram_err_tst1_t,
+ fcram_err_tst2_t, *p_fcram_err_tst2_t,
+ fcram_err_data_t, *p_fcram_err_data_t;
+
+
+
+#define FFLP_ERR_MSK_REG (FZC_FFLP + 0x20140)
+
+typedef union _fflp_err_mask_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:21;
+ uint32_t hash_tbl_dat:8;
+ uint32_t hash_tbl_lkup:1;
+ uint32_t tcam:1;
+ uint32_t vlan:1;
+#else
+ uint32_t vlan:1;
+ uint32_t tcam:1;
+ uint32_t hash_tbl_lkup:1;
+ uint32_t hash_tbl_dat:8;
+ uint32_t rsrvd:21;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fflp_err_mask_t, *p_fflp_err_mask_t;
+
+#define FFLP_ERR_VLAN_MASK 0x00000001ULL
+#define FFLP_ERR_VLAN 0x00000001ULL
+#define FFLP_ERR_VLAN_SHIFT 0x0
+
+#define FFLP_ERR_TCAM_MASK 0x00000002ULL
+#define FFLP_ERR_TCAM 0x00000001ULL
+#define FFLP_ERR_TCAM_SHIFT 0x1
+
+#define FFLP_ERR_HASH_TBL_LKUP_MASK 0x00000004ULL
+#define FFLP_ERR_HASH_TBL_LKUP 0x00000001ULL
+#define FFLP_ERR_HASH_TBL_LKUP_SHIFT 0x2
+
+#define FFLP_ERR_HASH_TBL_DAT_MASK 0x00000007F8ULL
+#define FFLP_ERR_HASH_TBL_DAT 0x0000000FFULL
+#define FFLP_ERR_HASH_TBL_DAT_SHIFT 0x3
+
+#define FFLP_ERR_MASK_ALL (FFLP_ERR_VLAN_MASK | FFLP_ERR_TCAM_MASK | \
+ FFLP_ERR_HASH_TBL_LKUP_MASK | \
+ FFLP_ERR_HASH_TBL_DAT_MASK)
+
+
+#define FFLP_CFG_1_REG (FZC_FFLP + 0x20100)
+
+typedef union _fflp_cfg_1_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:5;
+ uint32_t tcam_disable:1;
+ uint32_t pio_dbg_sel:3;
+ uint32_t pio_fio_rst:1;
+ uint32_t pio_fio_lat:2;
+ uint32_t camlatency:4;
+ uint32_t camratio:4;
+ uint32_t fcramratio:4;
+ uint32_t fcramoutdr:4;
+ uint32_t fcramqs:1;
+ uint32_t errordis:1;
+ uint32_t fflpinitdone:1;
+ uint32_t llcsnap:1;
+#else
+ uint32_t llcsnap:1;
+ uint32_t fflpinitdone:1;
+ uint32_t errordis:1;
+ uint32_t fcramqs:1;
+ uint32_t fcramoutdr:4;
+ uint32_t fcramratio:4;
+ uint32_t camratio:4;
+ uint32_t camlatency:4;
+ uint32_t pio_fio_lat:2;
+ uint32_t pio_fio_rst:1;
+ uint32_t pio_dbg_sel:3;
+ uint32_t tcam_disable:1;
+ uint32_t rsrvd:5;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fflp_cfg_1_t, *p_fflp_cfg_1_t;
+
+
+typedef enum fflp_fcram_output_drive {
+ FCRAM_OUTDR_NORMAL = 0x0,
+ FCRAM_OUTDR_STRONG = 0x5,
+ FCRAM_OUTDR_WEAK = 0xa
+} fflp_fcram_output_drive_t;
+
+
+typedef enum fflp_fcram_qs {
+ FCRAM_QS_MODE_QS = 0x0,
+ FCRAM_QS_MODE_FREE = 0x1
+} fflp_fcram_qs_t;
+
+#define FCRAM_PIO_HIGH_PRI 0xf
+#define FCRAM_PIO_MED_PRI 0xa
+#define FCRAM_LOOKUP_HIGH_PRI 0x0
+#define FCRAM_LOOKUP_HIGH_PRI 0x0
+#define FCRAM_IO_DEFAULT_PRI FCRAM_PIO_MED_PRI
+
+#define TCAM_PIO_HIGH_PRI 0xf
+#define TCAM_PIO_MED_PRI 0xa
+#define TCAM_LOOKUP_HIGH_PRI 0x0
+#define TCAM_LOOKUP_HIGH_PRI 0x0
+#define TCAM_IO_DEFAULT_PRI TCAM_PIO_MED_PRI
+
+#define TCAM_DEFAULT_LATENCY 0x4
+
+
+#define FFLP_DBG_TRAIN_VCT_REG (FZC_FFLP + 0x20148)
+
+typedef union _fflp_dbg_train_vct_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t vector;
+#else
+ uint32_t vector;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fflp_dbg_train_vct_t, *p_fflp_dbg_train_vct_t;
+
+
+
+#define FFLP_TCP_CFLAG_MSK_REG (FZC_FFLP + 0x20108)
+
+typedef union _tcp_cflag_mask_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:20;
+ uint32_t mask:12;
+#else
+ uint32_t mask:12;
+ uint32_t rsrvd:20;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tcp_cflag_mask_t, *p_tcp_cflag_mask_t;
+
+
+
+#define FFLP_FCRAM_REF_TMR_REG (FZC_FFLP + 0x20110)
+
+
+typedef union _fcram_ref_tmr_t {
+#define FCRAM_REFRESH_DEFAULT_MAX_TIME 0x200
+#define FCRAM_REFRESH_DEFAULT_MIN_TIME 0x200
+#define FCRAM_REFRESH_DEFAULT_SYS_TIME 0x200
+#define FCRAM_REFRESH_MAX_TICK 39 /* usecs */
+#define FCRAM_REFRESH_MIN_TICK 400 /* nsecs */
+
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t max:16;
+ uint32_t min:16;
+#else
+ uint32_t min:16;
+ uint32_t max:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fcram_ref_tmr_t, *p_fcram_ref_tmr_t;
+
+
+
+
+#define FFLP_FCRAM_FIO_ADDR_REG (FZC_FFLP + 0x20118)
+
+typedef union _fcram_fio_addr_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:22;
+ uint32_t addr:10;
+#else
+ uint32_t addr:10;
+ uint32_t rsrvd:22;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fcram_fio_addr_t, *p_fcram_fio_addr_t;
+
+
+#define FFLP_FCRAM_FIO_DAT_REG (FZC_FFLP + 0x20120)
+
+typedef union _fcram_fio_dat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:22;
+ uint32_t addr:10;
+#else
+ uint32_t addr:10;
+ uint32_t rsrvd:22;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fcram_fio_dat_t, *p_fcram_fio_dat_t;
+
+
+#define FFLP_FCRAM_PHY_RD_LAT_REG (FZC_FFLP + 0x20150)
+
+typedef union _fcram_phy_rd_lat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:24;
+ uint32_t lat:8;
+#else
+ uint32_t lat:8;
+ uint32_t rsrvd:24;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} fcram_phy_rd_lat_t, *p_fcram_phy_rd_lat_t;
+
+
+/*
+ * Specify how to build a flow key for IP
+ * classes, both programmable and hardwired
+ */
+#define FFLP_FLOW_KEY_BASE_OFFSET (FZC_FFLP + 0x40000)
+#define FFLP_FLOW_KEY_IP_USR4_REG (FZC_FFLP + 0x40000)
+#define FFLP_FLOW_KEY_IP_USR5_REG (FZC_FFLP + 0x40008)
+#define FFLP_FLOW_KEY_IP_USR6_REG (FZC_FFLP + 0x40010)
+#define FFLP_FLOW_KEY_IP_USR7_REG (FZC_FFLP + 0x40018)
+#define FFLP_FLOW_KEY_IP4_TCP_REG (FZC_FFLP + 0x40020)
+#define FFLP_FLOW_KEY_IP4_UDP_REG (FZC_FFLP + 0x40028)
+#define FFLP_FLOW_KEY_IP4_AH_ESP_REG (FZC_FFLP + 0x40030)
+#define FFLP_FLOW_KEY_IP4_SCTP_REG (FZC_FFLP + 0x40038)
+#define FFLP_FLOW_KEY_IP6_TCP_REG (FZC_FFLP + 0x40040)
+#define FFLP_FLOW_KEY_IP6_UDP_REG (FZC_FFLP + 0x40048)
+#define FFLP_FLOW_KEY_IP6_AH_ESP_REG (FZC_FFLP + 0x40050)
+#define FFLP_FLOW_KEY_IP6_SCTP_REG (FZC_FFLP + 0x40058)
+
+typedef union _flow_class_key_ip_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd2:22;
+ uint32_t port:1;
+ uint32_t l2da:1;
+ uint32_t vlan:1;
+ uint32_t ipsa:1;
+ uint32_t ipda:1;
+ uint32_t proto:1;
+ uint32_t l4_0:2;
+ uint32_t l4_1:2;
+#else
+ uint32_t l4_1:2;
+ uint32_t l4_0:2;
+ uint32_t proto:1;
+ uint32_t ipda:1;
+ uint32_t ipsa:1;
+ uint32_t vlan:1;
+ uint32_t l2da:1;
+ uint32_t port:1;
+ uint32_t rsrvd2:22;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} flow_class_key_ip_t, *p_flow_class_key_ip_t;
+
+
+#define FFLP_H1POLY_REG (FZC_FFLP + 0x40060)
+
+
+typedef union _hash_h1poly_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t init_value;
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_h1poly_t, *p_hash_h1poly_t;
+
+#define FFLP_H2POLY_REG (FZC_FFLP + 0x40068)
+
+typedef union _hash_h2poly_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:16;
+ uint32_t init_value:16;
+#else
+ uint32_t init_value:16;
+ uint32_t rsrvd:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_h2poly_t, *p_hash_h2poly_t;
+
+#define FFLP_FLW_PRT_SEL_REG (FZC_FFLP + 0x40070)
+
+
+typedef union _flow_prt_sel_t {
+#define FFLP_FCRAM_MAX_PARTITION 8
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd3:15;
+ uint32_t ext:1;
+ uint32_t rsrvd2:3;
+ uint32_t mask:5;
+ uint32_t rsrvd:3;
+ uint32_t base:5;
+#else
+ uint32_t base:5;
+ uint32_t rsrvd:3;
+ uint32_t mask:5;
+ uint32_t rsrvd2:3;
+ uint32_t ext:1;
+ uint32_t rsrvd3:15;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} flow_prt_sel_t, *p_flow_prt_sel_t;
+
+
+
+/* FFLP Offsets */
+
+
+#define FFLP_HASH_TBL_ADDR_REG (FFLP + 0x00000)
+
+typedef union _hash_tbl_addr_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t rsrvd:8;
+ uint32_t autoinc:1;
+ uint32_t addr:23;
+#else
+ uint32_t addr:23;
+ uint32_t autoinc:1;
+ uint32_t rsrvd:8;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_tbl_addr_t, *p_hash_tbl_addr_t;
+
+
+#define FFLP_HASH_TBL_DATA_REG (FFLP + 0x00008)
+
+typedef union _hash_tbl_data_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+ uint32_t ldw;
+#else
+ uint32_t ldw;
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_tbl_data_t, *p_hash_tbl_data_t;
+
+
+#define FFLP_HASH_TBL_DATA_LOG_REG (FFLP + 0x00010)
+
+
+typedef union _hash_tbl_data_log_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint32_t pio_err:1;
+ uint32_t fcram_addr:23;
+ uint32_t syndrome:8;
+#else
+ uint32_t syndrome:8;
+ uint32_t fcram_addr:23;
+ uint32_t pio_err:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} hash_tbl_data_log_t, *p_hash_tbl_data_log_t;
+
+
+
+#define REG_PIO_WRITE64(handle, offset, value) \
+ NXGE_REG_WR64((handle), (offset), (value))
+#define REG_PIO_READ64(handle, offset, val_p) \
+ NXGE_REG_RD64((handle), (offset), (val_p))
+
+
+#define WRITE_TCAM_REG_CTL(handle, ctl) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_CTL_REG, ctl)
+
+#define READ_TCAM_REG_CTL(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_CTL_REG, val_p)
+
+
+#define WRITE_TCAM_REG_KEY0(handle, key) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_KEY_0_REG, key)
+#define WRITE_TCAM_REG_KEY1(handle, key) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_KEY_1_REG, key)
+#define WRITE_TCAM_REG_KEY2(handle, key) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_KEY_2_REG, key)
+#define WRITE_TCAM_REG_KEY3(handle, key) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_KEY_3_REG, key)
+#define WRITE_TCAM_REG_MASK0(handle, mask) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_MASK_0_REG, mask)
+#define WRITE_TCAM_REG_MASK1(handle, mask) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_MASK_1_REG, mask)
+#define WRITE_TCAM_REG_MASK2(handle, mask) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_MASK_2_REG, mask)
+#define WRITE_TCAM_REG_MASK3(handle, mask) \
+ REG_PIO_WRITE64(handle, FFLP_TCAM_MASK_3_REG, mask)
+
+#define READ_TCAM_REG_KEY0(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_KEY_0_REG, val_p)
+#define READ_TCAM_REG_KEY1(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_KEY_1_REG, val_p)
+#define READ_TCAM_REG_KEY2(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_KEY_2_REG, val_p)
+#define READ_TCAM_REG_KEY3(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_KEY_3_REG, val_p)
+#define READ_TCAM_REG_MASK0(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_MASK_0_REG, val_p)
+#define READ_TCAM_REG_MASK1(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_MASK_1_REG, val_p)
+#define READ_TCAM_REG_MASK2(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_MASK_2_REG, val_p)
+#define READ_TCAM_REG_MASK3(handle, val_p) \
+ REG_PIO_READ64(handle, FFLP_TCAM_MASK_3_REG, val_p)
+
+
+
+
+typedef struct tcam_ipv4 {
+#if defined(_BIG_ENDIAN)
+ uint32_t reserved6; /* 255 : 224 */
+ uint32_t reserved5 : 24; /* 223 : 200 */
+ uint32_t cls_code : 5; /* 199 : 195 */
+ uint32_t reserved4 : 3; /* 194 : 192 */
+ uint32_t l2rd_tbl_num : 5; /* 191: 187 */
+ uint32_t noport : 1; /* 186 */
+ uint32_t reserved3 : 26; /* 185: 160 */
+ uint32_t reserved2; /* 159: 128 */
+ uint32_t reserved : 16; /* 127 : 112 */
+ uint32_t tos : 8; /* 111 : 104 */
+ uint32_t proto : 8; /* 103 : 96 */
+ uint32_t l4_port_spi; /* 95 : 64 */
+ uint32_t ip_src; /* 63 : 32 */
+ uint32_t ip_dest; /* 31 : 0 */
+#else
+ uint32_t ip_dest; /* 31 : 0 */
+ uint32_t ip_src; /* 63 : 32 */
+ uint32_t l4_port_spi; /* 95 : 64 */
+ uint32_t proto : 8; /* 103 : 96 */
+ uint32_t tos : 8; /* 111 : 104 */
+ uint32_t reserved : 16; /* 127 : 112 */
+ uint32_t reserved2; /* 159: 128 */
+ uint32_t reserved3 : 26; /* 185: 160 */
+ uint32_t noport : 1; /* 186 */
+ uint32_t l2rd_tbl_num : 5; /* 191: 187 */
+ uint32_t reserved4 : 3; /* 194 : 192 */
+ uint32_t cls_code : 5; /* 199 : 195 */
+ uint32_t reserved5 : 24; /* 223 : 200 */
+ uint32_t reserved6; /* 255 : 224 */
+#endif
+} tcam_ipv4_t;
+
+
+
+typedef struct tcam_reg {
+#if defined(_BIG_ENDIAN)
+ uint64_t reg0;
+ uint64_t reg1;
+ uint64_t reg2;
+ uint64_t reg3;
+#else
+ uint64_t reg3;
+ uint64_t reg2;
+ uint64_t reg1;
+ uint64_t reg0;
+#endif
+} tcam_reg_t;
+
+
+typedef struct tcam_ether {
+#if defined(_BIG_ENDIAN)
+ uint8_t reserved3[7]; /* 255 : 200 */
+ uint8_t cls_code : 5; /* 199 : 195 */
+ uint8_t reserved2 : 3; /* 194 : 192 */
+ uint8_t ethframe[11]; /* 191 : 104 */
+ uint8_t reserved[13]; /* 103 : 0 */
+#else
+ uint8_t reserved[13]; /* 103 : 0 */
+ uint8_t ethframe[11]; /* 191 : 104 */
+ uint8_t reserved2 : 3; /* 194 : 192 */
+ uint8_t cls_code : 5; /* 199 : 195 */
+ uint8_t reserved3[7]; /* 255 : 200 */
+#endif
+} tcam_ether_t;
+
+
+typedef struct tcam_ipv6 {
+#if defined(_BIG_ENDIAN)
+ uint32_t reserved4; /* 255 : 224 */
+ uint32_t reserved3 : 24; /* 223 : 200 */
+ uint32_t cls_code : 5; /* 199 : 195 */
+ uint32_t reserved2 : 3; /* 194 : 192 */
+ uint32_t l2rd_tbl_num : 5; /* 191: 187 */
+ uint32_t noport : 1; /* 186 */
+ uint32_t reserved : 10; /* 185 : 176 */
+ uint32_t tos : 8; /* 175 : 168 */
+ uint32_t nxt_hdr : 8; /* 167 : 160 */
+ uint32_t l4_port_spi; /* 159 : 128 */
+ uint32_t ip_addr[4]; /* 127 : 0 */
+#else
+ uint32_t ip_addr[4]; /* 127 : 0 */
+ uint32_t l4_port_spi; /* 159 : 128 */
+ uint32_t nxt_hdr : 8; /* 167 : 160 */
+ uint32_t tos : 8; /* 175 : 168 */
+ uint32_t reserved : 10; /* 185 : 176 */
+ uint32_t noport : 1; /* 186 */
+ uint32_t l2rd_tbl_num : 5; /* 191: 187 */
+ uint32_t reserved2 : 3; /* 194 : 192 */
+ uint32_t cls_code : 5; /* 199 : 195 */
+ uint32_t reserved3 : 24; /* 223 : 200 */
+ uint32_t reserved4; /* 255 : 224 */
+#endif
+} tcam_ipv6_t;
+
+
+typedef struct tcam_entry {
+ union _tcam_entry {
+ tcam_reg_t regs_e;
+ tcam_ether_t ether_e;
+ tcam_ipv4_t ipv4_e;
+ tcam_ipv6_t ipv6_e;
+ } key, mask;
+ tcam_res_t match_action;
+} tcam_entry_t;
+
+
+#define key_reg0 key.regs_e.reg0
+#define key_reg1 key.regs_e.reg1
+#define key_reg2 key.regs_e.reg2
+#define key_reg3 key.regs_e.reg3
+#define mask_reg0 mask.regs_e.reg0
+#define mask_reg1 mask.regs_e.reg1
+#define mask_reg2 mask.regs_e.reg2
+#define mask_reg3 mask.regs_e.reg3
+
+
+#define key0 key.regs_e.reg0
+#define key1 key.regs_e.reg1
+#define key2 key.regs_e.reg2
+#define key3 key.regs_e.reg3
+#define mask0 mask.regs_e.reg0
+#define mask1 mask.regs_e.reg1
+#define mask2 mask.regs_e.reg2
+#define mask3 mask.regs_e.reg3
+
+
+#define ip4_src_key key.ipv4_e.ip_src
+#define ip4_dest_key key.ipv4_e.ip_dest
+#define ip4_proto_key key.ipv4_e.proto
+#define ip4_port_key key.ipv4_e.l4_port_spi
+#define ip4_tos_key key.ipv4_e.tos
+#define ip4_noport_key key.ipv4_e.noport
+#define ip4_nrdc_key key.ipv4_e.l2rdc_tbl_num
+#define ip4_class_key key.ipv4_e.cls_code
+
+#define ip4_src_mask mask.ipv4_e.ip_src
+#define ip4_dest_mask mask.ipv4_e.ip_dest
+#define ip4_proto_mask mask.ipv4_e.proto
+#define ip4_port_mask mask.ipv4_e.l4_port_spi
+#define ip4_tos_mask mask.ipv4_e.tos
+#define ip4_nrdc_mask mask.ipv4_e.l2rdc_tbl_num
+#define ip4_noport_mask mask.ipv4_e.noport
+#define ip4_class_mask mask.ipv4_e.cls_code
+
+
+#define ip6_ip_addr_key key.ipv6_e.ip_addr
+#define ip6_port_key key.ipv6_e.l4_port_spi
+#define ip6_nxt_hdr_key key.ipv6_e.nxt_hdr
+#define ip6_tos_key key.ipv6_e.tos
+#define ip6_nrdc_key key.ipv6_e.l2rdc_tbl_num
+#define ip6_noport_key key.ipv6_e.noport
+#define ip6_class_key key.ipv6_e.cls_code
+
+
+#define ip6_ip_addr_mask mask.ipv6_e.ip_addr
+#define ip6_port_mask mask.ipv6_e.l4_port_spi
+#define ip6_nxt_hdr_mask mask.ipv6_e.nxt_hdr
+#define ip6_tos_mask mask.ipv6_e.tos
+#define ip6_nrdc_mask mask.ipv6_e.l2rdc_tbl_num
+#define ip6_noport_mask mask.ipv6_e.noport
+#define ip6_class_mask mask.ipv6_e.cls_code
+
+#define ether_class_key key.ether_e.cls_code
+#define ether_ethframe_key key.ether_e.ethframe
+#define ether_class_mask mask.ether_e.cls_code
+#define ether_ethframe_mask mask.ether_e.ethframe
+
+
+/*
+ * flow template structure
+ * The flow header is passed through the hash function
+ * which generates the H1 (and the H2 ) hash value.
+ * Hash computation is started at the 22 zeros.
+ *
+ * Since this structure uses the ip address fields,
+ * /usr/include/netinet/in.h has to be included
+ * before this header file.
+ * Need to move these includes to impl files ...
+ */
+
+#if defined(SOLARIS) || defined(COSIM)
+#include <netinet/in.h>
+#else
+#include <linux/in.h>
+#include <linux/in6.h>
+#endif
+
+
+typedef union flow_template {
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t l4_0:16; /* src port */
+ uint32_t l4_1:16; /* dest Port */
+
+ uint32_t pid:8;
+ uint32_t port:2;
+ uint32_t zeros:22; /* 0 */
+
+ union {
+ struct {
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+ } ip6_addr;
+
+ struct {
+ uint32_t rsrvd1;
+ struct in_addr daddr;
+ uint32_t rsrvd2[3];
+ struct in_addr saddr;
+ uint32_t rsrvd5[2];
+ } ip4_addr;
+ } ipaddr;
+
+ union {
+ uint64_t l2_info;
+ struct {
+ uint32_t vlan_valid : 4;
+ uint32_t l2da_1 : 28;
+ uint32_t l2da_0 : 20;
+ uint32_t vlanid : 12;
+
+ }l2_bits;
+ }l2;
+#else
+
+ uint32_t l4_1:16; /* dest Port */
+ uint32_t l4_0:16; /* src port */
+
+ uint32_t zeros:22; /* 0 */
+ uint32_t port:2;
+ uint32_t pid:8;
+
+ union {
+ struct {
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+ } ip6_addr;
+
+ struct {
+ uint32_t rsrvd1;
+ struct in_addr daddr;
+ uint32_t rsrvd2[3];
+ struct in_addr saddr;
+ uint32_t rsrvd5[2];
+ } ip4_addr;
+ } ipaddr;
+
+ union {
+ uint64_t l2_info;
+ struct {
+
+ uint32_t l2da_1 : 28;
+ uint32_t vlan_valid : 4;
+
+ uint32_t vlanid : 12;
+ uint32_t l2da_0 : 20;
+ }l2_bits;
+ }l2;
+#endif
+ } bits;
+
+} flow_template_t;
+
+
+
+#define ip4_saddr bits.ipaddr.ip4_addr.saddr.s_addr
+#define ip4_daddr bits.ipaddr.ip4_addr.daddr.s_addr
+
+#define ip_src_port bits.l4_0
+#define ip_dst_port bits.l4_1
+#define ip_proto bits.pid
+
+#define ip6_saddr bits.ipaddr.ip6_addr.saddr
+#define ip6_daddr bits.ipaddr.ip6_addr.daddr
+
+
+
+
+typedef struct _flow_key_cfg_t {
+ uint32_t rsrvd:23;
+ uint32_t use_portnum:1;
+ uint32_t use_l2da:1;
+ uint32_t use_vlan:1;
+ uint32_t use_saddr:1;
+ uint32_t use_daddr:1;
+ uint32_t use_sport:1;
+ uint32_t use_dport:1;
+ uint32_t use_proto:1;
+ uint32_t ip_opts_exist:1;
+} flow_key_cfg_t;
+
+
+typedef struct _tcam_key_cfg_t {
+ uint32_t rsrvd:28;
+ uint32_t use_ip_daddr:1;
+ uint32_t use_ip_saddr:1;
+ uint32_t lookup_enable:1;
+ uint32_t discard:1;
+} tcam_key_cfg_t;
+
+
+
+/*
+ * FCRAM Entry Formats
+ *
+ * ip6 and ip4 entries, the first 64 bits layouts are identical
+ * optimistic entry has only 64 bit layout
+ * The first three bits, fmt, ext and valid are the same
+ * accoross all the entries
+ */
+
+typedef union hash_optim {
+ uint64_t value;
+ struct _bits {
+#if defined(_BIG_ENDIAN)
+ uint32_t fmt : 1; /* 63 set to zero */
+ uint32_t ext : 1; /* 62 set to zero */
+ uint32_t valid : 1; /* 61 */
+ uint32_t rdc_offset : 5; /* 60 : 56 */
+ uint32_t h2 : 16; /* 55 : 40 */
+ uint32_t rsrvd : 8; /* 32 : 32 */
+ uint32_t usr_info; /* 31 : 0 */
+#else
+ uint32_t usr_info; /* 31 : 0 */
+ uint32_t rsrvd : 8; /* 39 : 32 */
+ uint32_t h2 : 16; /* 55 : 40 */
+ uint32_t rdc_offset : 5; /* 60 : 56 */
+ uint32_t valid : 1; /* 61 */
+ uint32_t ext : 1; /* 62 set to zero */
+ uint32_t fmt : 1; /* 63 set to zero */
+#endif
+ } bits;
+} hash_optim_t;
+
+
+typedef union _hash_hdr {
+ uint64_t value;
+ struct _exact_hdr {
+#if defined(_BIG_ENDIAN)
+ uint32_t fmt : 1; /* 63 1 for ipv6, 0 for ipv4 */
+ uint32_t ext : 1; /* 62 set to 1 */
+ uint32_t valid : 1; /* 61 */
+ uint32_t rsrvd : 1; /* 60 */
+ uint32_t l2da_1 : 28; /* 59 : 32 */
+ uint32_t l2da_0 : 20; /* 31 : 12 */
+ uint32_t vlan : 12; /* 12 : 0 */
+#else
+ uint32_t vlan : 12; /* 12 : 0 */
+ uint32_t l2da_0 : 20; /* 31 : 12 */
+ uint32_t l2da_1 : 28; /* 59 : 32 */
+ uint32_t rsrvd : 1; /* 60 */
+ uint32_t valid : 1; /* 61 */
+ uint32_t ext : 1; /* 62 set to 1 */
+ uint32_t fmt : 1; /* 63 1 for ipv6, 0 for ipv4 */
+#endif
+ } exact_hdr;
+ hash_optim_t optim_hdr;
+} hash_hdr_t;
+
+
+
+typedef union _hash_ports {
+ uint64_t value;
+ struct _ports_bits {
+#if defined(_BIG_ENDIAN)
+ uint32_t ip_dport : 16; /* 63 : 48 */
+ uint32_t ip_sport : 16; /* 47 : 32 */
+ uint32_t proto : 8; /* 31 : 24 */
+ uint32_t port : 2; /* 23 : 22 */
+ uint32_t rsrvd : 22; /* 21 : 0 */
+#else
+ uint32_t rsrvd : 22; /* 21 : 0 */
+ uint32_t port : 2; /* 23 : 22 */
+ uint32_t proto : 8; /* 31 : 24 */
+ uint32_t ip_sport : 16; /* 47 : 32 */
+ uint32_t ip_dport : 16; /* 63 : 48 */
+#endif
+ } ports_bits;
+} hash_ports_t;
+
+
+
+typedef union _hash_match_action {
+ uint64_t value;
+ struct _action_bits {
+#if defined(_BIG_ENDIAN)
+ uint32_t rsrvd2 : 3; /* 63 : 61 */
+ uint32_t rdc_offset : 5; /* 60 : 56 */
+ uint32_t zfvld : 1; /* 55 */
+ uint32_t rsrvd : 3; /* 54 : 52 */
+ uint32_t zfid : 12; /* 51 : 40 */
+ uint32_t _rsrvd : 8; /* 39 : 32 */
+ uint32_t usr_info; /* 31 : 0 */
+#else
+ uint32_t usr_info; /* 31 : 0 */
+ uint32_t _rsrvd : 8; /* 39 : 32 */
+ uint32_t zfid : 12; /* 51 : 40 */
+ uint32_t rsrvd : 3; /* 54 : 52 */
+ uint32_t zfvld : 1; /* 55 */
+ uint32_t rdc_offset : 5; /* 60 : 56 */
+ uint32_t rsrvd2 : 1; /* 63 : 61 */
+#endif
+ } action_bits;
+} hash_match_action_t;
+
+
+typedef struct _ipaddr6 {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+} ip6_addr_t;
+
+
+typedef struct _ipaddr4 {
+#if defined(_BIG_ENDIAN)
+ struct in_addr saddr;
+ struct in_addr daddr;
+#else
+ struct in_addr daddr;
+ struct in_addr saddr;
+#endif
+} ip4_addr_t;
+
+
+ /* ipv4 has 32 byte layout */
+
+typedef struct hash_ipv4 {
+ hash_hdr_t hdr;
+ ip4_addr_t ip_addr;
+ hash_ports_t proto_ports;
+ hash_match_action_t action;
+} hash_ipv4_t;
+
+
+ /* ipv4 has 56 byte layout */
+typedef struct hash_ipv6 {
+ hash_hdr_t hdr;
+ ip6_addr_t ip_addr;
+ hash_ports_t proto_ports;
+ hash_match_action_t action;
+} hash_ipv6_t;
+
+
+
+typedef union fcram_entry {
+ uint64_t value[8];
+ hash_tbl_data_t dreg[8];
+ hash_ipv6_t ipv6_entry;
+ hash_ipv4_t ipv4_entry;
+ hash_optim_t optim_entry;
+} fcram_entry_t;
+
+
+
+#define hash_hdr_fmt ipv4_entry.hdr.exact_hdr.fmt
+#define hash_hdr_ext ipv4_entry.hdr.exact_hdr.ext
+#define hash_hdr_valid ipv4_entry.hdr.exact_hdr.valid
+
+#define HASH_ENTRY_EXACT(fc) \
+ (fc->ipv4_entry.hdr.exact_hdr.ext == 1)
+#define HASH_ENTRY_OPTIM(fc) \
+ ((fc->ipv4_entry.hdr.exact_hdr.ext == 0) && \
+ (fc->ipv6_entry.hdr.exact_hdr.fmt == 0))
+#define HASH_ENTRY_EXACT_IP6(fc) \
+ ((fc->ipv6_entry.hdr.exact_hdr.fmt == 1) && \
+ (fc->ipv4_entry.hdr.exact_hdr.ext == 1))
+
+#define HASH_ENTRY_EXACT_IP4(fc) \
+ ((fc->ipv6_entry.hdr.exact_hdr.fmt == 0) && \
+ (fc->ipv4_entry.hdr.exact_hdr.ext == 1))
+
+#define HASH_ENTRY_TYPE(fc) \
+ (fc->ipv4_entry.hdr.exact_hdr.ext | \
+ (fc->ipv4_entry.hdr.exact_hdr.fmt << 1))
+
+
+
+typedef enum fcram_entry_format {
+ FCRAM_ENTRY_OPTIM = 0x0,
+ FCRAM_ENTRY_EX_IP4 = 0x2,
+ FCRAM_ENTRY_EX_IP6 = 0x3,
+ FCRAM_ENTRY_UNKOWN = 0x1
+} fcram_entry_format_t;
+
+
+#define HASH_ENTRY_TYPE_OPTIM FCRAM_ENTRY_OPTIM
+#define HASH_ENTRY_TYPE_OPTIM_IP4 FCRAM_ENTRY_OPTIM
+#define HASH_ENTRY_TYPE_OPTIM_IP4 FCRAM_ENTRY_OPTIM
+#define HASH_ENTRY_TYPE_EX_IP4 FCRAM_ENTRY_EX_IP4
+#define HASH_ENTRY_TYPE_EX_IP6 FCRAM_ENTRY_EX_IP6
+
+
+
+
+ /* error xxx formats */
+
+
+typedef struct _hash_lookup_err_log {
+ uint32_t rsrvd:28;
+ uint32_t lookup_err:1;
+ uint32_t ecc_err:1;
+ uint32_t uncor_err:1;
+ uint32_t multi_lkup:1;
+ uint32_t multi_bit:1;
+ uint32_t subarea:3;
+ uint32_t syndrome:8;
+ uint32_t h1:20;
+} hash_lookup_err_log_t, *p_hash_lookup_err_log_t;
+
+
+
+typedef struct _hash_pio_err_log {
+ uint32_t rsrvd:32;
+ uint32_t pio_err:1;
+ uint32_t syndrome:8;
+ uint32_t addr:23;
+} hash_pio_err_log_t, *p_hash_pio_err_log_t;
+
+
+
+typedef struct _tcam_err_log {
+ uint32_t rsrvd:2;
+ uint32_t tcam_err:1;
+ uint32_t parity_err:1;
+ uint32_t ecc_err:1;
+ uint32_t multi_lkup:1;
+ uint32_t location:8;
+ uint32_t syndrome:16;
+} tcam_err_log_t, *p_tcam_err_log_t;
+
+
+typedef struct _vlan_tbl_err_log {
+ uint32_t rsrvd:32;
+ uint32_t err:1;
+ uint32_t multi:1;
+ uint32_t addr:12;
+ uint32_t data:18;
+} vlan_tbl_err_log_t, *p_vlan_tbl_err_log_t;
+
+
+#define NEPTUNE_TCAM_SIZE 0x100
+#define NIU_TCAM_SIZE 0x80
+#define FCRAM_SIZE 0x100000
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_FFLP_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_flow.h b/usr/src/uts/sun4v/sys/nxge/nxge_flow.h
new file mode 100644
index 0000000000..7fd1d6ee09
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_flow.h
@@ -0,0 +1,198 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_FLOW_H
+#define _SYS_NXGE_NXGE_FLOW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(SOLARIS) && defined(_KERNEL)
+#include <netinet/in.h>
+#define S6_addr32 _S6_un._S6_u32
+#elif defined(LINUX) && defined(__KERNEL_)
+#include <linux/in.h>
+#include <linux/in6.h>
+#define S6_addr32 s6_addr32
+#elif defined(COSIM) || defined(IODIAG)
+#include <netinet/in.h>
+#if defined(LINUX)
+#define S6_addr32 s6_addr32
+#else
+#define S6_addr32 _S6_un._S6_u32
+#endif
+#endif
+
+
+typedef struct tcpip4_spec_s {
+ in_addr_t ip4src;
+ in_addr_t ip4dst;
+ in_port_t psrc;
+ in_port_t pdst;
+} tcpip4_spec_t;
+
+typedef struct tcpip6_spec_s {
+ struct in6_addr ip6src;
+ struct in6_addr ip6dst;
+ in_port_t psrc;
+ in_port_t pdst;
+} tcpip6_spec_t;
+
+typedef struct udpip4_spec_s {
+ in_addr_t ip4src;
+ in_addr_t ip4dst;
+ in_port_t psrc;
+ in_port_t pdst;
+} udpip4_spec_t;
+
+typedef struct udpip6_spec_s {
+ struct in6_addr ip6src;
+ struct in6_addr ip6dst;
+ in_port_t psrc;
+ in_port_t pdst;
+} udpip6_spec_t;
+
+typedef struct ahip4_spec_s {
+ in_addr_t ip4src;
+ in_addr_t ip4dst;
+ uint32_t spi;
+} ahip4_spec_t;
+
+typedef struct ahip6_spec_s {
+ struct in6_addr ip6src;
+ struct in6_addr ip6dst;
+ uint32_t spi;
+} ahip6_spec_t;
+
+typedef ahip4_spec_t espip4_spec_t;
+typedef ahip6_spec_t espip6_spec_t;
+
+typedef struct rawip4_spec_s {
+ struct in6_addr ip4src;
+ struct in6_addr ip4dst;
+ uint8_t hdata[64];
+} rawip4_spec_t;
+
+typedef struct rawip6_spec_s {
+ struct in6_addr ip6src;
+ struct in6_addr ip6dst;
+ uint8_t hdata[64];
+} rawip6_spec_t;
+
+
+typedef struct ether_spec_s {
+ uint16_t ether_type;
+ uint8_t frame_size;
+ uint8_t eframe[16];
+} ether_spec_t;
+
+
+typedef struct ip_user_spec_s {
+ uint8_t id;
+ uint8_t ip_ver;
+ uint8_t proto;
+ uint8_t tos_mask;
+ uint8_t tos;
+} ip_user_spec_t;
+
+
+
+typedef ether_spec_t arpip_spec_t;
+typedef ether_spec_t ether_user_spec_t;
+
+
+typedef struct flow_spec_s {
+ uint32_t flow_type;
+ union {
+ tcpip4_spec_t tcpip4spec;
+ tcpip6_spec_t tcpip6spec;
+ udpip4_spec_t udpip4spec;
+ udpip6_spec_t udpip6spec;
+ arpip_spec_t arpipspec;
+ ahip4_spec_t ahip4spec;
+ ahip6_spec_t ahip6spec;
+ espip4_spec_t espip4spec;
+ espip6_spec_t espip6spec;
+ rawip4_spec_t rawip4spec;
+ rawip6_spec_t rawip6spec;
+ ether_spec_t etherspec;
+ ip_user_spec_t ip_usr_spec;
+ uint8_t hdata[64];
+ } uh, um; /* entry, mask */
+} flow_spec_t;
+
+#define FSPEC_TCPIP4 0x1 /* TCP/IPv4 Flow */
+#define FSPEC_TCPIP6 0x2 /* TCP/IPv6 */
+#define FSPEC_UDPIP4 0x3 /* UDP/IPv4 */
+#define FSPEC_UDPIP6 0x4 /* UDP/IPv6 */
+#define FSPEC_ARPIP 0x5 /* ARP/IPv4 */
+#define FSPEC_AHIP4 0x6 /* AH/IP4 */
+#define FSPEC_AHIP6 0x7 /* AH/IP6 */
+#define FSPEC_ESPIP4 0x8 /* ESP/IP4 */
+#define FSPEC_ESPIP6 0x9 /* ESP/IP6 */
+#define FSPEC_SCTPIP4 0xA /* ESP/IP4 */
+#define FSPEC_SCTPIP6 0xB /* ESP/IP6 */
+#define FSPEC_RAW4 0xC /* RAW/IP4 */
+#define FSPEC_RAW6 0xD /* RAW/IP6 */
+#define FSPEC_ETHER 0xE /* ETHER Programmable */
+#define FSPEC_IP_USR 0xF /* IP Programmable */
+#define FSPEC_HDATA 0x10 /* Pkt Headers eth-da,sa,etype,ip,tcp(Bitmap) */
+
+
+#define TCAM_IPV6_ADDR(m32, ip6addr) { \
+ m32[0] = ip6addr.S6_addr32[0]; \
+ m32[1] = ip6addr.S6_addr32[1]; \
+ m32[2] = ip6addr.S6_addr32[2]; \
+ m32[3] = ip6addr.S6_addr32[3]; \
+ }
+
+
+#define TCAM_IPV4_ADDR(m32, ip4addr) (m32 = ip4addr)
+#define TCAM_IP_PORTS(port32, dp, sp) (port32 = dp | (sp << 16))
+#define TCAM_IP_CLASS(key, mask, class) { \
+ key = class; \
+ mask = 0x1f; \
+ }
+
+#define TCAM_IP_PROTO(key, mask, proto) { \
+ key = proto; \
+ mask = 0xff; \
+ }
+
+
+typedef struct flow_resource_s {
+ uint64_t channel_cookie;
+ uint64_t flow_cookie;
+ flow_spec_t flow_spec;
+} flow_resource_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_FLOW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_fm.h b/usr/src/uts/sun4v/sys/nxge/nxge_fm.h
new file mode 100644
index 0000000000..760d24bd20
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_fm.h
@@ -0,0 +1,247 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_FM_H
+#define _SYS_NXGE_NXGE_FM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/ddi.h>
+
+#define ERNAME_ERR_PORTN "port number"
+#define ERNAME_ERR_DCHAN "dma channel number"
+#define ERNAME_TCAM_ERR_LOG "tcam error log"
+#define ERNAME_VLANTAB_ERR_LOG "vlan table error log"
+#define ERNAME_HASHTAB_ERR_LOG "hash table error log"
+#define ERNAME_HASHT_LOOKUP_ERR_LOG0 "hash table lookup error log0"
+#define ERNAME_HASHT_LOOKUP_ERR_LOG1 "hash table lookup error log1"
+#define ERNAME_RDMC_PAR_ERR_LOG "rdmc parity error log"
+#define ERNAME_DFIFO_RD_PTR "dfifo read pointer"
+#define ERNAME_IPP_STATE_MACH "ipp state machine"
+#define ERNAME_DFIFO_ENTRY "dfifo entry"
+#define ERNAME_DFIFO_SYNDROME "dfifo syndrome"
+#define ERNAME_PFIFO_ENTRY "pfifo entry"
+#define ERNAME_ZCP_STATE_MACH "zcp state machine"
+#define ERNAME_CFIFO_PORT_NUM "cfifo port number"
+#define ERNAME_RDC_ERR_TYPE "completion error type"
+#define ERNAME_TDMC_ERR_LOG0 "tdmc error log0"
+#define ERNAME_TDMC_ERR_LOG1 "tdmc error log1"
+#define ERNAME_TXC_ROECC_ADDR "txc reorder FIFO ECC error address"
+#define ERNAME_TXC_ROECC_DATA0 "txc reorder FIFO data0"
+#define ERNAME_TXC_ROECC_DATA1 "txc reorder FIFO data1"
+#define ERNAME_TXC_ROECC_DATA2 "txc reorder FIFO data2"
+#define ERNAME_TXC_ROECC_DATA3 "txc reorder FIFO data3"
+#define ERNAME_TXC_ROECC_DATA4 "txc reorder FIFO data4"
+#define ERNAME_TXC_RO_STATE0 "txc reorder FIFO error state0" \
+ "(duplicate TID)"
+#define ERNAME_TXC_RO_STATE1 "txc reorder FIFO error state1" \
+ "(uninitialized TID)"
+#define ERNAME_TXC_RO_STATE2 "txc reorder FIFO error state2" \
+ "(timed out TIDs)"
+#define ERNAME_TXC_RO_STATE3 "txc reorder FIFO error state3"
+#define ERNAME_TXC_RO_STATE_CTL "txc reorder FIFO error control"
+#define ERNAME_TXC_RO_TIDS "txc reorder tids"
+#define ERNAME_TXC_SFECC_ADDR "txc store forward FIFO ECC error "\
+ "address"
+#define ERNAME_TXC_SFECC_DATA0 "txc store forward FIFO data0"
+#define ERNAME_TXC_SFECC_DATA1 "txc store forward FIFO data1"
+#define ERNAME_TXC_SFECC_DATA2 "txc store forward FIFO data2"
+#define ERNAME_TXC_SFECC_DATA3 "txc store forward FIFO data3"
+#define ERNAME_TXC_SFECC_DATA4 "txc store forward FIFO data4"
+
+#define EREPORT_FM_ID_SHIFT 16
+#define EREPORT_FM_ID_MASK 0xFF
+#define EREPORT_INDEX_MASK 0xFF
+#define NXGE_FM_EREPORT_UNKNOWN 0
+
+#define FM_SW_ID 0xFF
+#define FM_PCS_ID MAC_BLK_ID
+#define FM_TXMAC_ID TXMAC_BLK_ID
+#define FM_RXMAC_ID RXMAC_BLK_ID
+#define FM_MIF_ID MIF_BLK_ID
+#define FM_IPP_ID IPP_BLK_ID
+#define FM_TXC_ID TXC_BLK_ID
+#define FM_TXDMA_ID TXDMA_BLK_ID
+#define FM_RXDMA_ID RXDMA_BLK_ID
+#define FM_ZCP_ID ZCP_BLK_ID
+#define FM_ESPC_ID ESPC_BLK_ID
+#define FM_FFLP_ID FFLP_BLK_ID
+#define FM_PCIE_ID PCIE_BLK_ID
+#define FM_ETHER_SERDES_ID ETHER_SERDES_BLK_ID
+#define FM_PCIE_SERDES_ID PCIE_SERDES_BLK_ID
+#define FM_VIR_ID VIR_BLK_ID
+
+typedef uint32_t nxge_fm_ereport_id_t;
+
+typedef struct _nxge_fm_ereport_attr {
+ uint32_t index;
+ char *eclass;
+ ddi_fault_impact_t impact;
+} nxge_fm_ereport_attr_t;
+
+/* General MAC ereports */
+typedef enum {
+ NXGE_FM_EREPORT_XPCS_LINK_DOWN = (FM_PCS_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT,
+ NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT,
+ NXGE_FM_EREPORT_PCS_LINK_DOWN,
+ NXGE_FM_EREPORT_PCS_REMOTE_FAULT
+} nxge_fm_ereport_pcs_t;
+
+/* MIF ereports */
+typedef enum {
+ NXGE_FM_EREPORT_MIF_ACCESS_FAIL = (FM_MIF_ID << EREPORT_FM_ID_SHIFT)
+} nxge_fm_ereport_mif_t;
+
+/* FFLP ereports */
+typedef enum {
+ NXGE_FM_EREPORT_FFLP_TCAM_ERR = (FM_FFLP_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR,
+ NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR,
+ NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR,
+ NXGE_FM_EREPORT_FFLP_ACCESS_FAIL
+} nxge_fm_ereport_fflp_t;
+
+/* IPP ereports */
+typedef enum {
+ NXGE_FM_EREPORT_IPP_EOP_MISS = (FM_IPP_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_IPP_SOP_MISS,
+ NXGE_FM_EREPORT_IPP_DFIFO_UE,
+ NXGE_FM_EREPORT_IPP_DFIFO_CE,
+ NXGE_FM_EREPORT_IPP_PFIFO_PERR,
+ NXGE_FM_EREPORT_IPP_ECC_ERR_MAX,
+ NXGE_FM_EREPORT_IPP_PFIFO_OVER,
+ NXGE_FM_EREPORT_IPP_PFIFO_UND,
+ NXGE_FM_EREPORT_IPP_BAD_CS_MX,
+ NXGE_FM_EREPORT_IPP_PKT_DIS_MX,
+ NXGE_FM_EREPORT_IPP_RESET_FAIL
+} nxge_fm_ereport_ipp_t;
+
+/* RDMC ereports */
+typedef enum {
+ NXGE_FM_EREPORT_RDMC_DCF_ERR = (FM_RXDMA_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR,
+ NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR,
+ NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR,
+ NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR,
+ NXGE_FM_EREPORT_RDMC_RBR_TMOUT,
+ NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR,
+ NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS,
+ NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR,
+ NXGE_FM_EREPORT_RDMC_ID_MISMATCH,
+ NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR,
+ NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR,
+ NXGE_FM_EREPORT_RDMC_COMPLETION_ERR,
+ NXGE_FM_EREPORT_RDMC_CONFIG_ERR,
+ NXGE_FM_EREPORT_RDMC_RCRINCON,
+ NXGE_FM_EREPORT_RDMC_RCRFULL,
+ NXGE_FM_EREPORT_RDMC_RBRFULL,
+ NXGE_FM_EREPORT_RDMC_RBRLOGPAGE,
+ NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE
+} nxge_fm_ereport_rdmc_t;
+
+/* ZCP ereports */
+typedef enum {
+ NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN =
+ (FM_ZCP_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR,
+ NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR,
+ NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR,
+ NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR,
+ NXGE_FM_EREPORT_ZCP_CFIFO_ECC,
+ NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN,
+ NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW,
+ NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR,
+ NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR,
+ NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR,
+ NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR,
+ NXGE_FM_EREPORT_ZCP_ACCESS_FAIL
+} nxge_fm_ereport_zcp_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_RXMAC_UNDERFLOW = (FM_RXMAC_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP,
+ NXGE_FM_EREPORT_RXMAC_RESET_FAIL
+} nxge_fm_ereport_rxmac_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR =
+ (FM_TXDMA_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_TDMC_MBOX_ERR,
+ NXGE_FM_EREPORT_TDMC_NACK_PREF,
+ NXGE_FM_EREPORT_TDMC_NACK_PKT_RD,
+ NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR,
+ NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW,
+ NXGE_FM_EREPORT_TDMC_CONF_PART_ERR,
+ NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR,
+ NXGE_FM_EREPORT_TDMC_RESET_FAIL
+} nxge_fm_ereport_attr_tdmc_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR =
+ (FM_TXC_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR,
+ NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR,
+ NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR,
+ NXGE_FM_EREPORT_TXC_ASSY_DEAD,
+ NXGE_FM_EREPORT_TXC_REORDER_ERR
+} nxge_fm_ereport_attr_txc_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_TXMAC_UNDERFLOW =
+ (FM_TXMAC_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_TXMAC_OVERFLOW,
+ NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR,
+ NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR,
+ NXGE_FM_EREPORT_TXMAC_RESET_FAIL
+} nxge_fm_ereport_attr_txmac_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_ESPC_ACCESS_FAIL = (FM_ESPC_ID << EREPORT_FM_ID_SHIFT)
+} nxge_fm_ereport_espc_t;
+
+typedef enum {
+ NXGE_FM_EREPORT_SW_INVALID_PORT_NUM = (FM_SW_ID << EREPORT_FM_ID_SHIFT),
+ NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM,
+ NXGE_FM_EREPORT_SW_INVALID_PARAM
+} nxge_fm_ereport_sw_t;
+
+#define NXGE_FM_EREPORT_UNKNOWN 0
+#define NXGE_FM_EREPORT_UNKNOWN_NAME ""
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_FM_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_fzc.h b/usr/src/uts/sun4v/sys/nxge/nxge_fzc.h
new file mode 100644
index 0000000000..9be1e787d3
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_fzc.h
@@ -0,0 +1,93 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_FZC_H
+#define _SYS_NXGE_NXGE_FZC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <npi_vir.h>
+
+nxge_status_t nxge_fzc_intr_init(p_nxge_t);
+nxge_status_t nxge_fzc_intr_ldg_num_set(p_nxge_t);
+nxge_status_t nxge_fzc_intr_tmres_set(p_nxge_t);
+nxge_status_t nxge_fzc_intr_sid_set(p_nxge_t);
+
+nxge_status_t nxge_fzc_dmc_rx_log_page_vld(p_nxge_t, uint16_t,
+ uint32_t, boolean_t);
+nxge_status_t nxge_fzc_dmc_rx_log_page_mask(p_nxge_t, uint16_t,
+ uint32_t, uint32_t, uint32_t);
+
+void nxge_init_fzc_txdma_channels(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_txdma_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+nxge_status_t nxge_init_fzc_txdma_port(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel(p_nxge_t, uint16_t,
+ p_rx_rbr_ring_t, p_rx_rcr_ring_t, p_rx_mbox_t);
+
+nxge_status_t nxge_init_fzc_rdc_tbl(p_nxge_t);
+nxge_status_t nxge_init_fzc_rx_common(p_nxge_t);
+nxge_status_t nxge_init_fzc_rxdma_port(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel_pages(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel_red(p_nxge_t,
+ uint16_t, p_rx_rcr_ring_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel_clrlog(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t);
+
+nxge_status_t nxge_init_fzc_txdma_channel_pages(p_nxge_t,
+ uint16_t, p_tx_ring_t);
+
+nxge_status_t nxge_init_fzc_txdma_channel_drr(p_nxge_t, uint16_t,
+ p_tx_ring_t);
+
+nxge_status_t nxge_init_fzc_txdma_port(p_nxge_t);
+
+void nxge_init_fzc_ldg_num(p_nxge_t);
+void nxge_init_fzc_sys_int_data(p_nxge_t);
+void nxge_init_fzc_ldg_int_timer(p_nxge_t);
+nxge_status_t nxge_fzc_sys_err_mask_set(p_nxge_t, uint64_t);
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+nxge_status_t nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t);
+nxge_status_t nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t,
+ uint16_t, p_tx_ring_t);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_FZC_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_hw.h
new file mode 100644
index 0000000000..961d4ff8dd
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_hw.h
@@ -0,0 +1,1057 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_HW_H
+#define _SYS_NXGE_NXGE_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) && \
+ !defined(__BIG_ENDIAN) && !defined(__LITTLE_ENDIAN)
+#error Host endianness not defined
+#endif
+
+#if !defined(_BIT_FIELDS_HTOL) && !defined(_BIT_FIELDS_LTOH) && \
+ !defined(__BIT_FIELDS_HTOL) && !defined(__BIT_FIELDS_LTOH)
+#error Bit ordering not defined
+#endif
+
+#include <nxge_fflp_hw.h>
+#include <nxge_ipp_hw.h>
+#include <nxge_mac_hw.h>
+#include <nxge_rxdma_hw.h>
+#include <nxge_txc_hw.h>
+#include <nxge_txdma_hw.h>
+#include <nxge_zcp_hw.h>
+#include <nxge_espc_hw.h>
+#include <nxge_n2_esr_hw.h>
+#include <nxge_sr_hw.h>
+#include <nxge_phy_hw.h>
+
+
+/* Modes of NXGE core */
+typedef enum nxge_mode_e {
+ NXGE_MODE_NE = 1,
+ NXGE_MODE_N2 = 2
+} nxge_mode_t;
+
+/*
+ * Function control Register
+ * (bit 31 is reset to 0. Read back 0 then free to use it.
+ * (once done with it, bit 0:15 can be used to store SW status)
+ */
+#define DEV_FUNC_SR_REG (PIO + 0x10000)
+#define DEV_FUNC_SR_SR_SHIFT 0
+#define DEV_FUNC_SR_SR_MASK 0x000000000000FFFFULL
+#define DEV_FUNC_SR_FUNCID_SHIFT 16
+#define DEV_FUNC_SR_FUNCID_MASK 0x0000000000030000ULL
+#define DEV_FUNC_SR_TAS_SHIFT 31
+#define DEV_FUNC_SR_TAS_MASK 0x0000000080000000ULL
+
+typedef union _dev_func_sr_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t tas:1;
+ uint32_t res2:13;
+ uint32_t funcid:2;
+ uint32_t sr:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sr:16;
+ uint32_t funcid:2;
+ uint32_t res2:13;
+ uint32_t tas:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} dev_func_sr_t, *p_dev_func_sr_t;
+
+
+/*
+ * Multi Parition Control Register (partitiion manager)
+ */
+#define MULTI_PART_CTL_REG (FZC_PIO + 0x00000)
+#define MULTI_PART_CTL_MPC 0x0000000000000001ULL
+
+typedef union _multi_part_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:31;
+ uint32_t mpc:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mpc:1;
+ uint32_t res1:31;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} multi_part_ctl_t, *p_multi_part_ctl_t;
+
+/*
+ * Virtual DMA CSR Address (partition manager)
+ */
+#define VADDR_REG (PIO_VADDR + 0x00000)
+
+/*
+ * DMA Channel Binding Register (partition manager)
+ */
+#define DMA_BIND_REG (FZC_PIO + 0x10000)
+#define DMA_BIND_RX_SHIFT 0
+#define DMA_BIND_RX_MASK 0x000000000000001FULL
+#define DMA_BIND_RX_BIND_SHIFT 5
+#define DMA_BIND_RX_BIND_SET 0x0000000000000020ULL
+#define DMA_BIND_RX_BIND_MASK 0x0000000000000020ULL
+#define DMA_BIND_TX_SHIFT 8
+#define DMA_BIND_TX_MASK 0x0000000000001f00ULL
+#define DMA_BIND_TX_BIND_SHIFT 13
+#define DMA_BIND_TX_BIND_SET 0x0000000000002000ULL
+#define DMA_BIND_TX_BIND_MASK 0x0000000000002000ULL
+
+typedef union _dma_bind_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:16;
+ uint32_t tx_bind:1;
+ uint32_t tx:5;
+ uint32_t res2:2;
+ uint32_t rx_bind:1;
+ uint32_t rx:5;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rx:5;
+ uint32_t rx_bind:1;
+ uint32_t res2:2;
+ uint32_t tx:5;
+ uint32_t tx_bind:1;
+ uint32_t res1_1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} dma_bind_t, *p_dma_bind_t;
+
+/*
+ * System interrupts:
+ * Logical device and group definitions.
+ */
+#define NXGE_INT_MAX_LDS 69
+#define NXGE_INT_MAX_LDGS 64
+#define NXGE_LDGRP_PER_NIU_PORT (NXGE_INT_MAX_LDGS/2)
+#define NXGE_LDGRP_PER_NEP_PORT (NXGE_INT_MAX_LDGS/4)
+#define NXGE_LDGRP_PER_2PORTS (NXGE_INT_MAX_LDGS/2)
+#define NXGE_LDGRP_PER_4PORTS (NXGE_INT_MAX_LDGS/4)
+
+#define NXGE_RDMA_LD_START 0
+#define NXGE_TDMA_LD_START 32
+#define NXGE_MIF_LD 63
+#define NXGE_MAC_LD_START 64
+#define NXGE_MAC_LD_PORT0 64
+#define NXGE_MAC_LD_PORT1 65
+#define NXGE_MAC_LD_PORT2 66
+#define NXGE_MAC_LD_PORT3 67
+#define NXGE_SYS_ERROR_LD 68
+
+/*
+ * Logical Device Group Number
+ */
+#define LDG_NUM_REG (FZC_PIO + 0x20000)
+#define LDG_NUM_NUM_SHIFT 0
+#define LDG_NUM_NUM_MASK 0x000000000000001FULL
+
+typedef union _ldg_num_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:26;
+ uint32_t num:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t num:6;
+ uint32_t res1_1:26;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ldg_num_t, *p_ldg_num_t;
+
+/*
+ * Logical Device State Vector
+ */
+#define LDSV0_REG (PIO_LDSV + 0x00000)
+#define LDSV0_LDF_SHIFT 0
+#define LDSV0_LDF_MASK 0x00000000000003FFULL
+#define LDG_NUM_NUM_MASK 0x000000000000001FULL
+#define LDSV_MASK_ALL 0x0000000000000001ULL
+
+/*
+ * Logical Device State Vector 1
+ */
+#define LDSV1_REG (PIO_LDSV + 0x00008)
+
+/*
+ * Logical Device State Vector 2
+ */
+#define LDSV2_REG (PIO_LDSV + 0x00010)
+
+/* For Logical Device State Vector 0 and 1 */
+typedef union _ldsv_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ uint32_t ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ldsv_t, *p_ldsv_t;
+
+#define LDSV2_LDF0_SHIFT 0
+#define LDSV2_LDF0_MASK 0x000000000000001FULL
+#define LDSV2_LDF1_SHIFT 5
+#define LDSV2_LDF1_MASK 0x00000000000001E0ULL
+
+typedef union _ldsv2_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:22;
+ uint32_t ldf1:5;
+ uint32_t ldf0:5;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ldf0:5;
+ uint32_t ldf1:5;
+ uint32_t res1_1:22;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ldsv2_t, *p_ldsv2_t;
+
+/*
+ * Logical Device Interrupt Mask 0
+ */
+#define LD_IM0_REG (PIO_IMASK0 + 0x00000)
+#define LD_IM0_SHIFT 0
+#define LD_IM0_MASK 0x0000000000000003ULL
+#define LD_IM_MASK 0x0000000000000003ULL
+
+/*
+ * Logical Device Interrupt Mask 1
+ */
+#define LD_IM1_REG (PIO_IMASK1 + 0x00000)
+#define LD_IM1_SHIFT 0
+#define LD_IM1_MASK 0x0000000000000003ULL
+
+/* For Lofical Device Interrupt Mask 0 and 1 */
+typedef union _ld_im_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:30;
+ uint32_t ldf_mask:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ldf_mask:2;
+ uint32_t res1_1:30;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ld_im_t, *p_ld_im_t;
+
+/*
+ * Logical Device Group Interrupt Management
+ */
+#define LDGIMGN_REG (PIO_LDSV + 0x00018)
+#define LDGIMGN_TIMER_SHIFT 0
+#define LDGIMGM_TIMER_MASK 0x000000000000003FULL
+#define LDGIMGN_ARM_SHIFT 31
+#define LDGIMGM_ARM 0x0000000080000000ULL
+#define LDGIMGM_ARM_MASK 0x0000000080000000ULL
+
+typedef union _ldgimgm_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t arm:1;
+ uint32_t res2:25;
+ uint32_t timer:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t timer:6;
+ uint32_t res2:25;
+ uint32_t arm:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ldgimgm_t, *p_ldgimgm_t;
+
+/*
+ * Logical Device Group Interrupt Timer Resolution
+ */
+#define LDGITMRES_REG (FZC_PIO + 0x00008)
+#define LDGTITMRES_RES_SHIFT 0 /* bits 19:0 */
+#define LDGTITMRES_RES_MASK 0x00000000000FFFFFULL
+typedef union _ldgitmres_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:12;
+ uint32_t res:20;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res:20;
+ uint32_t res1_1:12;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} ldgitmres_t, *p_ldgitmres_t;
+
+/*
+ * System Interrupt Data
+ */
+#define SID_REG (FZC_PIO + 0x10200)
+#define SID_DATA_SHIFT 0 /* bits 6:0 */
+#define SID_DATA_MASK 0x000000000000007FULL
+#define SID_DATA_INTNUM_SHIFT 0 /* bits 4:0 */
+#define SID_DATA_INTNUM_MASK 0x000000000000001FULL
+#define SID_DATA_FUNCNUM_SHIFT 5 /* bits 6:5 */
+#define SID_DATA_FUNCNUM_MASK 0x0000000000000060ULL
+#define SID_PCI_FUNCTION_SHIFT (1 << 5)
+#define SID_N2_INDEX (1 << 6)
+
+#define SID_DATA(f, v) ((f << SID_DATA_FUNCNUM_SHIFT) | \
+ ((v << SID_DATA_SHIFT) & SID_DATA_INTNUM_MASK))
+
+#define SID_DATA_N2(v) (v | SID_N2_INDEX)
+
+typedef union _sid_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:25;
+ uint32_t data:7;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t data:7;
+ uint32_t res1_1:25;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} sid_t, *p_sid_t;
+
+/*
+ * Reset Control
+ */
+#define RST_CTL_REG (FZC_PIO + 0x00038)
+#define RST_CTL_MAC_RST3 0x0000000000400000ULL
+#define RST_CTL_MAC_RST3_SHIFT 22
+#define RST_CTL_MAC_RST2 0x0000000000200000ULL
+#define RST_CTL_MAC_RST2_SHIFT 21
+#define RST_CTL_MAC_RST1 0x0000000000100000ULL
+#define RST_CTL_MAC_RST1_SHIFT 20
+#define RST_CTL_MAC_RST0 0x0000000000080000ULL
+#define RST_CTL_MAC_RST0_SHIFT 19
+#define RST_CTL_EN_ACK_TO 0x0000000000000800ULL
+#define RST_CTL_EN_ACK_TO_SHIFT 11
+#define RST_CTL_ACK_TO_MASK 0x00000000000007FEULL
+#define RST_CTL_ACK_TO_SHIFT 1
+
+
+typedef union _rst_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:9;
+ uint32_t mac_rst3:1;
+ uint32_t mac_rst2:1;
+ uint32_t mac_rst1:1;
+ uint32_t mac_rst0:1;
+ uint32_t res2:7;
+ uint32_t ack_to_en:1;
+ uint32_t ack_to_val:10;
+ uint32_t res3:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res3:1;
+ uint32_t ack_to_val:10;
+ uint32_t ack_to_en:1;
+ uint32_t res2:7;
+ uint32_t mac_rst0:1;
+ uint32_t mac_rst1:1;
+ uint32_t mac_rst2:1;
+ uint32_t mac_rst3:1;
+ uint32_t res1:9;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rst_ctl_t, *p_rst_ctl_t;
+
+/*
+ * System Error Mask
+ */
+#define SYS_ERR_MASK_REG (FZC_PIO + 0x00090)
+
+/*
+ * System Error Status
+ */
+#define SYS_ERR_STAT_REG (FZC_PIO + 0x00098)
+
+
+#define SYS_ERR_META2_MASK 0x0000000000000400ULL
+#define SYS_ERR_META2_SHIFT 10
+#define SYS_ERR_META1_MASK 0x0000000000000200ULL
+#define SYS_ERR_META1_SHIFT 9
+#define SYS_ERR_PEU_MASK 0x0000000000000100ULL
+#define SYS_ERR_PEU_SHIFT 8
+#define SYS_ERR_TXC_MASK 0x0000000000000080ULL
+#define SYS_ERR_TXC_SHIFT 7
+#define SYS_ERR_RDMC_MASK 0x0000000000000040ULL
+#define SYS_ERR_RDMC_SHIFT 6
+#define SYS_ERR_TDMC_MASK 0x0000000000000020ULL
+#define SYS_ERR_TDMC_SHIFT 5
+#define SYS_ERR_ZCP_MASK 0x0000000000000010ULL
+#define SYS_ERR_ZCP_SHIFT 4
+#define SYS_ERR_FFLP_MASK 0x0000000000000008ULL
+#define SYS_ERR_FFLP_SHIFT 3
+#define SYS_ERR_IPP_MASK 0x0000000000000004ULL
+#define SYS_ERR_IPP_SHIFT 2
+#define SYS_ERR_MAC_MASK 0x0000000000000002ULL
+#define SYS_ERR_MAC_SHIFT 1
+#define SYS_ERR_SMX_MASK 0x0000000000000001ULL
+#define SYS_ERR_SMX_SHIFT 0
+#define SYS_ERR_MASK_ALL (SYS_ERR_SMX_MASK | SYS_ERR_MAC_MASK | \
+ SYS_ERR_IPP_MASK | SYS_ERR_FFLP_MASK | \
+ SYS_ERR_ZCP_MASK | SYS_ERR_TDMC_MASK | \
+ SYS_ERR_RDMC_MASK | SYS_ERR_TXC_MASK | \
+ SYS_ERR_PEU_MASK | SYS_ERR_META1_MASK | \
+ SYS_ERR_META2_MASK)
+
+
+typedef union _sys_err_mask_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:21;
+ uint32_t meta2:1;
+ uint32_t meta1:1;
+ uint32_t peu:1;
+ uint32_t txc:1;
+ uint32_t rdmc:1;
+ uint32_t tdmc:1;
+ uint32_t zcp:1;
+ uint32_t fflp:1;
+ uint32_t ipp:1;
+ uint32_t mac:1;
+ uint32_t smx:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t smx:1;
+ uint32_t mac:1;
+ uint32_t ipp:1;
+ uint32_t fflp:1;
+ uint32_t zcp:1;
+ uint32_t tdmc:1;
+ uint32_t rdmc:1;
+ uint32_t txc:1;
+ uint32_t peu:1;
+ uint32_t meta1:1;
+ uint32_t meta2:1;
+ uint32_t res:21;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} sys_err_mask_t, sys_err_stat_t, *p_sys_err_mask_t, *p_sys_err_stat_t;
+
+
+/*
+ * Meta Arbiter Dirty Transaction ID Control
+ */
+
+#define DIRTY_TID_CTL_REG (FZC_PIO + 0x0010)
+#define DIRTY_TID_CTL_WR_THRES_MASK 0x00000000003F0000ULL
+#define DIRTY_TID_CTL_WR_THRES_SHIFT 16
+#define DIRTY_TID_CTL_RD_THRES_MASK 0x00000000000003F0ULL
+#define DIRTY_TID_CTL_RD_THRES_SHIFT 4
+#define DIRTY_TID_CTL_DTID_CLR 0x0000000000000002ULL
+#define DIRTY_TID_CTL_DTID_CLR_SHIFT 1
+#define DIRTY_TID_CTL_DTID_EN 0x0000000000000001ULL
+#define DIRTY_TID_CTL_DTID_EN_SHIFT 0
+
+typedef union _dty_tid_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:10;
+ uint32_t np_wr_thres_val:6;
+ uint32_t res2:6;
+ uint32_t np_rd_thres_val:6;
+ uint32_t res3:2;
+ uint32_t dty_tid_clr:1;
+ uint32_t dty_tid_en:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dty_tid_en:1;
+ uint32_t dty_tid_clr:1;
+ uint32_t res3:2;
+ uint32_t np_rd_thres_val:6;
+ uint32_t res2:6;
+ uint32_t np_wr_thres_val:6;
+ uint32_t res1:10;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} dty_tid_ctl_t, *p_dty_tid_ctl_t;
+
+
+/*
+ * Meta Arbiter Dirty Transaction ID Status
+ */
+#define DIRTY_TID_STAT_REG (FZC_PIO + 0x0018)
+#define DIRTY_TID_STAT_WR_TID_DTY_CNT_MASK 0x0000000000003F00ULL
+#define DIRTY_TID_STAT_WR_TID_DTY_CNT_SHIFT 8
+#define DIRTY_TID_STAT_RD_TID_DTY_CNT_MASK 0x000000000000003FULL
+#define DIRTY_TID_STAT_RD_TID_DTY_CNT_SHIFT 0
+
+typedef union _dty_tid_stat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:18;
+ uint32_t wr_tid_dirty_cnt:6;
+ uint32_t res2:2;
+ uint32_t rd_tid_dirty_cnt:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rd_tid_dirty_cnt:6;
+ uint32_t res2:2;
+ uint32_t wr_tid_dirty_cnt:6;
+ uint32_t res1:18;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} dty_tid_stat_t, *p_dty_tid_stat_t;
+
+
+/*
+ * SMX Registers
+ */
+#define SMX_CFIG_DAT_REG (FZC_PIO + 0x00040)
+#define SMX_CFIG_DAT_RAS_DET_EN_MASK 0x0000000080000000ULL
+#define SMX_CFIG_DAT_RAS_DET_EN_SHIFT 31
+#define SMX_CFIG_DAT_RAS_INJ_EN_MASK 0x0000000040000000ULL
+#define SMX_CFIG_DAT_RAS_INJ_EN_SHIFT 30
+#define SMX_CFIG_DAT_TRANS_TO_MASK 0x000000000FFFFFFFULL
+#define SMX_CFIG_DAT_TRANS_TO_SHIFT 0
+
+typedef union _smx_cfg_dat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_err_det:1;
+ uint32_t ras_err_inj_en:1;
+ uint32_t res:2;
+ uint32_t trans_to_val:28;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t trans_to_val:28;
+ uint32_t res:2;
+ uint32_t ras_err_inj_en:1;
+ uint32_t res_err_det:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} smx_cfg_dat_t, *p_smx_cfg_dat_t;
+
+
+#define SMX_INT_STAT_REG (FZC_PIO + 0x00048)
+#define SMX_INT_STAT_SM_MASK 0x00000000FFFFFFC0ULL
+#define SMX_INT_STAT_SM_SHIFT 6
+
+typedef union _smx_int_stat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t st_mc_stat:26;
+ uint32_t res:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res:6;
+ uint32_t st_mc_stat:26;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} smx_int_stat_t, *p_smx_int_stat_t;
+
+
+#define SMX_CTL_REG (FZC_PIO + 0x00050)
+
+typedef union _smx_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:21;
+ uint32_t resp_err_inj:3;
+ uint32_t res2:1;
+ uint32_t xtb_err_inj:3;
+ uint32_t res3:1;
+ uint32_t dbg_sel:3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dbg_sel:3;
+ uint32_t res3:1;
+ uint32_t xtb_err_inj:3;
+ uint32_t res2:1;
+ uint32_t resp_err_inj:3;
+ uint32_t res1:21;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} smx_ctl_t, *p_smx_ctl_t;
+
+
+#define SMX_DBG_VEC_REG (FZC_PIO + 0x00058)
+
+typedef union _smx_dbg_vec_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t dbg_tng_vec;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} smx_dbg_vec_t, *p_smx_dbg_vec_t;
+
+
+/*
+ * Debug registers
+ */
+
+#define PIO_DBG_SEL_REG (FZC_PIO + 0x00060)
+
+typedef union _pio_dbg_sel_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t sel;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pio_dbg_sel_t, *p_pio_dbg_sel_t;
+
+
+#define PIO_TRAIN_VEC_REG (FZC_PIO + 0x00068)
+
+typedef union _pio_tng_vec_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t training_vec;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pio_tng_vec_t, *p_pio_tng_vec_t;
+
+#define PIO_ARB_CTL_REG (FZC_PIO + 0x00070)
+
+typedef union _pio_arb_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t ctl;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pio_arb_ctl_t, *p_pio_arb_ctl_t;
+
+#define PIO_ARB_DBG_VEC_REG (FZC_PIO + 0x00078)
+
+typedef union _pio_arb_dbg_vec_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t dbg_vector;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pio_arb_dbg_vec_t, *p_pio_arb_dbg_vec_t;
+
+
+/*
+ * GPIO Registers
+ */
+
+#define GPIO_EN_REG (FZC_PIO + 0x00028)
+#define GPIO_EN_ENABLE_MASK 0x000000000000FFFFULL
+#define GPIO_EN_ENABLE_SHIFT 0
+typedef union _gpio_en_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:16;
+ uint32_t enable:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t enable:16;
+ uint32_t res:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} gpio_en_t, *p_gpio_en_t;
+
+#define GPIO_DATA_IN_REG (FZC_PIO + 0x00030)
+#define GPIO_DATA_IN_MASK 0x000000000000FFFFULL
+#define GPIO_DATA_IN_SHIFT 0
+typedef union _gpio_data_in_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:16;
+ uint32_t data_in:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t data_in:16;
+ uint32_t res:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} gpio_data_in_t, *p_gpio_data_in_t;
+
+
+/*
+ * PCI Express Interface Module (PIM) registers
+ */
+#define PIM_CONTROL_REG (FZC_PIM + 0x0)
+#define PIM_CONTROL_DBG_SEL_MASK 0x000000000000000FULL
+#define PIM_CONTROL_DBG_SEL_SHIFT 0
+typedef union _pim_ctl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:28;
+ uint32_t dbg_sel:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dbg_sel:4;
+ uint32_t res:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pim_ctl_t, *p_pim_ctl_t;
+
+#define PIM_DBG_TRAINING_VEC_REG (FZC_PIM + 0x00008)
+#define PIM_DBG_TRAINING_VEC_MASK 0x00000000FFFFFFFFULL
+
+#define PIM_INTR_STATUS_REG (FZC_PIM + 0x00010)
+#define PIM_INTR_STATUS_MASK 0x00000000FFFFFFFFULL
+
+#define PIM_INTERNAL_STATUS_REG (FZC_PIM + 0x00018)
+#define PIM_INTERNAL_STATUS_MASK 0x00000000FFFFFFFFULL
+
+#define PIM_INTR_MASK_REG (FZC_PIM + 0x00020)
+#define PIM_INTR_MASK_MASK 0x00000000FFFFFFFFULL
+
+/*
+ * Partitioning Logical pages Definition registers.
+ * (used by both receive and transmit DMA channels)
+ */
+
+/* Logical page definitions */
+typedef union _log_page_vld_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:28;
+ uint32_t func:2;
+ uint32_t page1:1;
+ uint32_t page0:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t page0:1;
+ uint32_t page1:1;
+ uint32_t func:2;
+ uint32_t res1_1:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} log_page_vld_t, *p_log_page_vld_t;
+
+
+#define DMA_LOG_PAGE_MASK_SHIFT 0
+#define DMA_LOG_PAGE_MASK_MASK 0x00000000ffffffffULL
+
+/* Receive Logical Page Mask */
+typedef union _log_page_mask_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t mask:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mask:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} log_page_mask_t, *p_log_page_mask_t;
+
+
+/* Receive Logical Page Value */
+#define DMA_LOG_PAGE_VALUE_SHIFT 0
+#define DMA_LOG_PAGE_VALUE_MASK 0x00000000ffffffffULL
+
+/* Receive Logical Page Value */
+typedef union _log_page_value_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t value:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t value:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} log_page_value_t, *p_log_page_value_t;
+
+/* Receive Logical Page Relocation */
+#define DMA_LOG_PAGE_RELO_SHIFT 0 /* bits 31:0 */
+#define DMA_LOG_PAGE_RELO_MASK 0x00000000ffffffffULL
+
+/* Receive Logical Page Relocation */
+typedef union _log_page_relo_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t relo:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t relo:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} log_page_relo_t, *p_log_page_relo_t;
+
+
+/* Receive Logical Page Handle */
+#define DMA_LOG_PAGE_HANDLE_SHIFT 0 /* bits 19:0 */
+#define DMA_LOG_PAGE_HANDLE_MASK 0x00000000ffffffffULL
+
+/* Receive Logical Page Handle */
+typedef union _log_page_hdl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:12;
+ uint32_t handle:20;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t handle:20;
+ uint32_t res1_1:12;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} log_page_hdl_t, *p_log_page_hdl_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_impl.h b/usr/src/uts/sun4v/sys/nxge/nxge_impl.h
new file mode 100644
index 0000000000..4ebfda8dc9
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_impl.h
@@ -0,0 +1,857 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_IMPL_H
+#define _SYS_NXGE_NXGE_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NIU HV API version definitions.
+ */
+#define NIU_MAJOR_VER 1
+#define NIU_MINOR_VER 1
+
+/*
+ * NIU HV API v1.0 definitions
+ */
+#define N2NIU_RX_LP_CONF 0x142
+#define N2NIU_RX_LP_INFO 0x143
+#define N2NIU_TX_LP_CONF 0x144
+#define N2NIU_TX_LP_INFO 0x145
+
+#ifndef _ASM
+
+#include <sys/types.h>
+#include <sys/byteorder.h>
+#include <sys/debug.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strlog.h>
+#ifndef COSIM
+#include <sys/strsubr.h>
+#endif
+#include <sys/cmn_err.h>
+#include <sys/vtrace.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/strsun.h>
+#include <sys/stat.h>
+#include <sys/cpu.h>
+#include <sys/kstat.h>
+#include <inet/common.h>
+#include <inet/ip.h>
+#include <sys/dlpi.h>
+#include <inet/nd.h>
+#include <netinet/in.h>
+#include <sys/ethernet.h>
+#include <sys/vlan.h>
+#include <sys/pci.h>
+#include <sys/taskq.h>
+#include <sys/atomic.h>
+
+#include <sys/nxge/nxge_defs.h>
+#include <sys/nxge/nxge_hw.h>
+#include <sys/nxge/nxge_mac.h>
+#include <sys/nxge/nxge_mii.h>
+#include <sys/nxge/nxge_fm.h>
+#if !defined(IODIAG)
+#include <sys/netlb.h>
+#endif
+
+#include <sys/ddi_intr.h>
+
+#if defined(_KERNEL)
+#include <sys/mac.h>
+#include <sys/mac_impl.h>
+#include <sys/mac_ether.h>
+#endif
+
+#if defined(sun4v)
+#include <sys/hypervisor_api.h>
+#include <sys/machsystm.h>
+#include <sys/hsvc.h>
+#endif
+
+/*
+ * Handy macros (taken from bge driver)
+ */
+#define RBR_SIZE 4
+#define DMA_COMMON_CHANNEL(area) ((area.dma_channel))
+#define DMA_COMMON_VPTR(area) ((area.kaddrp))
+#define DMA_COMMON_VPTR_INDEX(area, index) \
+ (((char *)(area.kaddrp)) + \
+ (index * RBR_SIZE))
+#define DMA_COMMON_HANDLE(area) ((area.dma_handle))
+#define DMA_COMMON_ACC_HANDLE(area) ((area.acc_handle))
+#define DMA_COMMON_IOADDR(area) ((area.dma_cookie.dmac_laddress))
+#define DMA_COMMON_IOADDR_INDEX(area, index) \
+ ((area.dma_cookie.dmac_laddress) + \
+ (index * RBR_SIZE))
+
+#define DMA_NPI_HANDLE(area) ((area.npi_handle)
+
+#define DMA_COMMON_SYNC(area, flag) ((void) ddi_dma_sync((area).dma_handle,\
+ (area).offset, (area).alength, \
+ (flag)))
+#define DMA_COMMON_SYNC_OFFSET(area, bufoffset, len, flag) \
+ ((void) ddi_dma_sync((area).dma_handle,\
+ (area.offset + bufoffset), len, \
+ (flag)))
+
+#define DMA_COMMON_SYNC_RBR_DESC(area, index, flag) \
+ ((void) ddi_dma_sync((area).dma_handle,\
+ (index * RBR_SIZE), RBR_SIZE, \
+ (flag)))
+
+#define DMA_COMMON_SYNC_RBR_DESC_MULTI(area, index, count, flag) \
+ ((void) ddi_dma_sync((area).dma_handle,\
+ (index * RBR_SIZE), count * RBR_SIZE, \
+ (flag)))
+#define DMA_COMMON_SYNC_ENTRY(area, index, flag) \
+ ((void) ddi_dma_sync((area).dma_handle,\
+ (index * (area).block_size), \
+ (area).block_size, \
+ (flag)))
+
+#define NEXT_ENTRY(index, wrap) ((index + 1) & wrap)
+#define NEXT_ENTRY_PTR(ptr, first, last) \
+ ((ptr == last) ? first : (ptr + 1))
+
+/*
+ * NPI related macros
+ */
+#define NXGE_DEV_NPI_HANDLE(nxgep) (nxgep->npi_handle)
+
+#define NPI_PCI_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_pci_handle.regh = ah)
+#define NPI_PCI_ADD_HANDLE_SET(nxgep, ap) (nxgep->npi_pci_handle.regp = ap)
+
+#define NPI_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_handle.regh = ah)
+#define NPI_ADD_HANDLE_SET(nxgep, ap) \
+ nxgep->npi_handle.is_vraddr = B_FALSE; \
+ nxgep->npi_handle.function.instance = nxgep->instance; \
+ nxgep->npi_handle.function.function = nxgep->function_num; \
+ nxgep->npi_handle.nxgep = (void *) nxgep; \
+ nxgep->npi_handle.regp = ap;
+
+#define NPI_REG_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_reg_handle.regh = ah)
+#define NPI_REG_ADD_HANDLE_SET(nxgep, ap) \
+ nxgep->npi_reg_handle.is_vraddr = B_FALSE; \
+ nxgep->npi_handle.function.instance = nxgep->instance; \
+ nxgep->npi_handle.function.function = nxgep->function_num; \
+ nxgep->npi_reg_handle.nxgep = (void *) nxgep; \
+ nxgep->npi_reg_handle.regp = ap;
+
+#define NPI_MSI_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_msi_handle.regh = ah)
+#define NPI_MSI_ADD_HANDLE_SET(nxgep, ap) (nxgep->npi_msi_handle.regp = ap)
+
+#define NPI_VREG_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_vreg_handle.regh = ah)
+#define NPI_VREG_ADD_HANDLE_SET(nxgep, ap) \
+ nxgep->npi_vreg_handle.is_vraddr = B_TRUE; \
+ nxgep->npi_handle.function.instance = nxgep->instance; \
+ nxgep->npi_handle.function.function = nxgep->function_num; \
+ nxgep->npi_vreg_handle.nxgep = (void *) nxgep; \
+ nxgep->npi_vreg_handle.regp = ap;
+
+#define NPI_V2REG_ACC_HANDLE_SET(nxgep, ah) (nxgep->npi_v2reg_handle.regh = ah)
+#define NPI_V2REG_ADD_HANDLE_SET(nxgep, ap) \
+ nxgep->npi_v2reg_handle.is_vraddr = B_TRUE; \
+ nxgep->npi_handle.function.instance = nxgep->instance; \
+ nxgep->npi_handle.function.function = nxgep->function_num; \
+ nxgep->npi_v2reg_handle.nxgep = (void *) nxgep; \
+ nxgep->npi_v2reg_handle.regp = ap;
+
+#define NPI_PCI_ACC_HANDLE_GET(nxgep) (nxgep->npi_pci_handle.regh)
+#define NPI_PCI_ADD_HANDLE_GET(nxgep) (nxgep->npi_pci_handle.regp)
+#define NPI_ACC_HANDLE_GET(nxgep) (nxgep->npi_handle.regh)
+#define NPI_ADD_HANDLE_GET(nxgep) (nxgep->npi_handle.regp)
+#define NPI_REG_ACC_HANDLE_GET(nxgep) (nxgep->npi_reg_handle.regh)
+#define NPI_REG_ADD_HANDLE_GET(nxgep) (nxgep->npi_reg_handle.regp)
+#define NPI_MSI_ACC_HANDLE_GET(nxgep) (nxgep->npi_msi_handle.regh)
+#define NPI_MSI_ADD_HANDLE_GET(nxgep) (nxgep->npi_msi_handle.regp)
+#define NPI_VREG_ACC_HANDLE_GET(nxgep) (nxgep->npi_vreg_handle.regh)
+#define NPI_VREG_ADD_HANDLE_GET(nxgep) (nxgep->npi_vreg_handle.regp)
+#define NPI_V2REG_ACC_HANDLE_GET(nxgep) (nxgep->npi_v2reg_handle.regh)
+#define NPI_V2REG_ADD_HANDLE_GET(nxgep) (nxgep->npi_v2reg_handle.regp)
+
+#define NPI_DMA_ACC_HANDLE_SET(dmap, ah) (dmap->npi_handle.regh = ah)
+#define NPI_DMA_ACC_HANDLE_GET(dmap) (dmap->npi_handle.regh)
+
+/*
+ * DMA handles.
+ */
+#define NXGE_DESC_D_HANDLE_GET(desc) (desc.dma_handle)
+#define NXGE_DESC_D_IOADD_GET(desc) (desc.dma_cookie.dmac_laddress)
+#define NXGE_DMA_IOADD_GET(dma_cookie) (dma_cookie.dmac_laddress)
+#define NXGE_DMA_AREA_IOADD_GET(dma_area) (dma_area.dma_cookie.dmac_laddress)
+
+#define LDV_ON(ldv, vector) ((vector >> ldv) & 0x1)
+#define LDV2_ON_1(ldv, vector) ((vector >> (ldv - 64)) & 0x1)
+#define LDV2_ON_2(ldv, vector) (((vector >> 5) >> (ldv - 64)) & 0x1)
+
+typedef uint32_t nxge_status_t;
+
+typedef enum {
+ IDLE,
+ PROGRESS,
+ CONFIGURED
+} dev_func_shared_t;
+
+typedef enum {
+ DVMA,
+ DMA,
+ SDMA
+} dma_method_t;
+
+typedef enum {
+ BKSIZE_4K,
+ BKSIZE_8K,
+ BKSIZE_16K,
+ BKSIZE_32K
+} nxge_rx_block_size_t;
+
+#ifdef TX_ONE_BUF
+#define TX_BCOPY_MAX 1514
+#else
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+#define TX_BCOPY_MAX 4096
+#define TX_BCOPY_SIZE 4096
+#else
+#define TX_BCOPY_MAX 2048
+#define TX_BCOPY_SIZE 2048
+#endif
+#endif
+
+#define TX_STREAM_MIN 512
+#define TX_FASTDVMA_MIN 1024
+
+#define NXGE_ERROR_SHOW_MAX 0
+
+/*
+ * Defaults
+ */
+#define NXGE_RDC_RCR_THRESHOLD 8
+#define NXGE_RDC_RCR_TIMEOUT 16
+
+#define NXGE_RDC_RCR_THRESHOLD_MAX 256
+#define NXGE_RDC_RCR_TIMEOUT_MAX 64
+#define NXGE_RDC_RCR_THRESHOLD_MIN 1
+#define NXGE_RDC_RCR_TIMEOUT_MIN 1
+#define NXGE_RCR_FULL_HEADER 1
+
+#define NXGE_IS_VLAN_PACKET(ptr) \
+ ((((struct ether_vlan_header *)ptr)->ether_tpid) == \
+ htons(VLAN_ETHERTYPE))
+
+typedef enum {
+ NONE,
+ SMALL,
+ MEDIUM,
+ LARGE
+} dma_size_t;
+
+typedef enum {
+ USE_NONE,
+ USE_BCOPY,
+ USE_DVMA,
+ USE_DMA,
+ USE_SDMA
+} dma_type_t;
+
+typedef enum {
+ NOT_IN_USE,
+ HDR_BUF,
+ MTU_BUF,
+ RE_ASSEMBLY_BUF,
+ FREE_BUF
+} rx_page_state_t;
+
+struct _nxge_block_mv_t {
+ uint32_t msg_type;
+ dma_type_t dma_type;
+};
+
+typedef struct _nxge_block_mv_t nxge_block_mv_t, *p_nxge_block_mv_t;
+
+typedef enum {
+ NEPTUNE, /* 4 ports */
+ NEPTUNE_2, /* 2 ports */
+ N2_NIU /* N2/NIU 2 ports */
+} niu_type_t;
+
+typedef enum {
+ CFG_DEFAULT = 0, /* default cfg */
+ CFG_EQUAL, /* Equal */
+ CFG_FAIR, /* Equal */
+ CFG_CLASSIFY,
+ CFG_L2_CLASSIFY,
+ CFG_L3_CLASSIFY,
+ CFG_L3_DISTRIBUTE,
+ CFG_L3_WEB,
+ CFG_L3_TCAM,
+ CFG_NOT_SPECIFIED,
+ CFG_CUSTOM /* Custom */
+} cfg_type_t;
+
+typedef enum {
+ NO_MSG = 0x0, /* No message output or storage. */
+ CONSOLE = 0x1, /* Messages are go to the console. */
+ BUFFER = 0x2, /* Messages are go to the system buffer. */
+ CON_BUF = 0x3, /* Messages are go to the console and */
+ /* system buffer. */
+ VERBOSE = 0x4 /* Messages are go out only in VERBOSE node. */
+} out_msg_t, *p_out_msg_t;
+
+typedef enum {
+ DBG_NO_MSG = 0x0, /* No message output or storage. */
+ DBG_CONSOLE = 0x1, /* Messages are go to the console. */
+ DBG_BUFFER = 0x2, /* Messages are go to the system buffer. */
+ DBG_CON_BUF = 0x3, /* Messages are go to the console and */
+ /* system buffer. */
+ STR_LOG = 4 /* Sessage sent to streams logging driver. */
+} out_dbgmsg_t, *p_out_dbgmsg_t;
+
+
+
+#if defined(_KERNEL) || defined(COSIM)
+
+typedef struct ether_addr ether_addr_st, *p_ether_addr_t;
+typedef struct ether_header ether_header_t, *p_ether_header_t;
+typedef queue_t *p_queue_t;
+
+#if !defined(IODIAG)
+typedef mblk_t *p_mblk_t;
+#endif
+
+/*
+ * Common DMA data elements.
+ */
+struct _nxge_dma_common_t {
+ uint16_t dma_channel;
+ void *kaddrp;
+ void *first_kaddrp;
+ void *last_kaddrp;
+ void *ioaddr_pp;
+ void *first_ioaddr_pp;
+ void *last_ioaddr_pp;
+ ddi_dma_cookie_t dma_cookie;
+ uint32_t ncookies;
+
+ nxge_block_mv_t msg_dma_flags;
+ ddi_dma_handle_t dma_handle;
+ nxge_os_acc_handle_t acc_handle;
+ npi_handle_t npi_handle;
+
+ size_t block_size;
+ uint32_t nblocks;
+ size_t alength;
+ uint_t offset;
+ uint_t dma_chunk_index;
+ void *orig_ioaddr_pp;
+ uint64_t orig_vatopa;
+ void *orig_kaddrp;
+ size_t orig_alength;
+ boolean_t contig_alloc_type;
+};
+
+typedef struct _nxge_t nxge_t, *p_nxge_t;
+typedef struct _nxge_dma_common_t nxge_dma_common_t, *p_nxge_dma_common_t;
+
+typedef struct _nxge_dma_pool_t {
+ p_nxge_dma_common_t *dma_buf_pool_p;
+ uint32_t ndmas;
+ uint32_t *num_chunks;
+ boolean_t buf_allocated;
+} nxge_dma_pool_t, *p_nxge_dma_pool_t;
+
+/*
+ * Each logical device (69):
+ * - LDG #
+ * - flag bits
+ * - masks.
+ * - interrupt handler function.
+ *
+ * Generic system interrupt handler with two arguments:
+ * (nxge_sys_intr_t)
+ * Per device instance data structure
+ * Logical group data structure.
+ *
+ * Logical device interrupt handler with two arguments:
+ * (nxge_ldv_intr_t)
+ * Per device instance data structure
+ * Logical device number
+ */
+typedef struct _nxge_ldg_t nxge_ldg_t, *p_nxge_ldg_t;
+typedef struct _nxge_ldv_t nxge_ldv_t, *p_nxge_ldv_t;
+typedef uint_t (*nxge_sys_intr_t)(void *arg1, void *arg2);
+typedef uint_t (*nxge_ldv_intr_t)(void *arg1, void *arg2);
+
+/*
+ * Each logical device Group (64) needs to have the following
+ * configurations:
+ * - timer counter (6 bits)
+ * - timer resolution (20 bits, number of system clocks)
+ * - system data (7 bits)
+ */
+struct _nxge_ldg_t {
+ uint8_t ldg; /* logical group number */
+ uint8_t vldg_index;
+ boolean_t arm;
+ boolean_t interrupted;
+ uint16_t ldg_timer; /* counter */
+ uint8_t func;
+ uint8_t vector;
+ uint8_t intdata;
+ uint8_t nldvs;
+ p_nxge_ldv_t ldvp;
+ nxge_sys_intr_t sys_intr_handler;
+ uint_t (*ih_cb_func)(caddr_t, caddr_t);
+ p_nxge_t nxgep;
+};
+
+struct _nxge_ldv_t {
+ uint8_t ldg_assigned;
+ uint8_t ldv;
+ boolean_t is_rxdma;
+ boolean_t is_txdma;
+ boolean_t is_mif;
+ boolean_t is_mac;
+ boolean_t is_syserr;
+ boolean_t use_timer;
+ uint8_t channel;
+ uint8_t vdma_index;
+ uint8_t func;
+ p_nxge_ldg_t ldgp;
+ uint8_t ldv_flags;
+ boolean_t is_leve;
+ boolean_t is_edge;
+ uint8_t ldv_ldf_masks;
+ nxge_ldv_intr_t ldv_intr_handler;
+ uint_t (*ih_cb_func)(caddr_t, caddr_t);
+ p_nxge_t nxgep;
+};
+#endif
+
+typedef struct _nxge_logical_page_t {
+ uint16_t dma;
+ uint16_t page;
+ boolean_t valid;
+ uint64_t mask;
+ uint64_t value;
+ uint64_t reloc;
+ uint32_t handle;
+} nxge_logical_page_t, *p_nxge_logical_page_t;
+
+/*
+ * (Internal) return values from ioctl subroutines.
+ */
+enum nxge_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 */
+};
+
+typedef struct _pci_cfg_t {
+ uint16_t vendorid;
+ uint16_t devid;
+ uint16_t command;
+ uint16_t status;
+ uint8_t revid;
+ uint8_t res0;
+ uint16_t junk1;
+ uint8_t cache_line;
+ uint8_t latency;
+ uint8_t header;
+ uint8_t bist;
+ uint32_t base;
+ uint32_t base14;
+ uint32_t base18;
+ uint32_t base1c;
+ uint32_t base20;
+ uint32_t base24;
+ uint32_t base28;
+ uint32_t base2c;
+ uint32_t base30;
+ uint32_t res1[2];
+ uint8_t int_line;
+ uint8_t int_pin;
+ uint8_t min_gnt;
+ uint8_t max_lat;
+} pci_cfg_t, *p_pci_cfg_t;
+
+#if defined(_KERNEL) || defined(COSIM)
+
+typedef struct _dev_regs_t {
+ nxge_os_acc_handle_t nxge_pciregh; /* PCI config DDI IO handle */
+ p_pci_cfg_t nxge_pciregp; /* mapped PCI registers */
+
+ nxge_os_acc_handle_t nxge_regh; /* device DDI IO (BAR 0) */
+ void *nxge_regp; /* mapped device registers */
+
+ nxge_os_acc_handle_t nxge_msix_regh; /* MSI/X DDI handle (BAR 2) */
+ void *nxge_msix_regp; /* MSI/X register */
+
+ nxge_os_acc_handle_t nxge_vir_regh; /* virtualization (BAR 4) */
+ unsigned char *nxge_vir_regp; /* virtualization register */
+
+ nxge_os_acc_handle_t nxge_vir2_regh; /* second virtualization */
+ unsigned char *nxge_vir2_regp; /* second virtualization */
+
+ nxge_os_acc_handle_t nxge_romh; /* fcode rom handle */
+ unsigned char *nxge_romp; /* fcode pointer */
+} dev_regs_t, *p_dev_regs_t;
+
+/*
+ * Driver alternate mac address structure.
+ */
+typedef struct _nxge_mmac_t {
+ kmutex_t mmac_lock;
+ uint8_t max_num_mmac; /* Max allocated per card */
+ uint8_t num_mmac; /* Mac addr. per function */
+ struct ether_addr mmac_pool[16]; /* Mac addr pool per function in s/w */
+ boolean_t rsv_mmac[16]; /* Reserved mac addr. in the pool */
+ uint8_t num_avail_mmac; /* # of rsv.ed mac addr. in the pool */
+} nxge_mmac_t;
+
+/*
+ * mmac stats structure
+ */
+typedef struct _nxge_mmac_stats_t {
+ uint8_t mmac_max_cnt;
+ uint8_t mmac_avail_cnt;
+ struct ether_addr mmac_avail_pool[16];
+} nxge_mmac_stats_t, *p_nxge_mmac_stats_t;
+
+#define NXGE_MAX_MMAC_ADDRS 32
+#define NXGE_NUM_MMAC_ADDRS 8
+#define NXGE_NUM_OF_PORTS 4
+
+#endif
+
+#include <sys/nxge/nxge_common_impl.h>
+#include <sys/nxge/nxge_common.h>
+#include <sys/nxge/nxge_txc.h>
+#include <sys/nxge/nxge_rxdma.h>
+#include <sys/nxge/nxge_txdma.h>
+#include <sys/nxge/nxge_fflp.h>
+#include <sys/nxge/nxge_ipp.h>
+#include <sys/nxge/nxge_zcp.h>
+#include <sys/nxge/nxge_fzc.h>
+#include <sys/nxge/nxge_flow.h>
+#include <sys/nxge/nxge_virtual.h>
+
+#include <sys/nxge/nxge.h>
+
+#include <sys/modctl.h>
+#include <sys/pattr.h>
+
+#include <npi_vir.h>
+
+/*
+ * Reconfiguring the network devices requires the net_config privilege
+ * in Solaris 10+. Prior to this, root privilege is required. In order
+ * that the driver binary can run on both S10+ and earlier versions, we
+ * make the decisiion as to which to use at runtime. These declarations
+ * allow for either (or both) to exist ...
+ */
+extern int secpolicy_net_config(const cred_t *, boolean_t);
+extern int drv_priv(cred_t *);
+extern void nxge_fm_report_error(p_nxge_t, uint8_t,
+ uint8_t, nxge_fm_ereport_id_t);
+
+#pragma weak secpolicy_net_config
+
+/* nxge_classify.c */
+nxge_status_t nxge_classify_init(p_nxge_t);
+nxge_status_t nxge_set_hw_classify_config(p_nxge_t);
+
+/* nxge_fflp.c */
+void nxge_put_tcam(p_nxge_t, p_mblk_t);
+void nxge_get_tcam(p_nxge_t, p_mblk_t);
+nxge_status_t nxge_classify_init_hw(p_nxge_t);
+nxge_status_t nxge_classify_init_sw(p_nxge_t);
+nxge_status_t nxge_fflp_ip_class_config_all(p_nxge_t);
+nxge_status_t nxge_fflp_ip_class_config(p_nxge_t, tcam_class_t,
+ uint32_t);
+
+nxge_status_t nxge_fflp_ip_class_config_get(p_nxge_t,
+ tcam_class_t,
+ uint32_t *);
+
+nxge_status_t nxge_cfg_ip_cls_flow_key(p_nxge_t, tcam_class_t,
+ uint32_t);
+
+nxge_status_t nxge_fflp_ip_usr_class_config(p_nxge_t, tcam_class_t,
+ uint32_t);
+
+uint64_t nxge_classify_get_cfg_value(p_nxge_t, uint8_t, uint8_t);
+nxge_status_t nxge_add_flow(p_nxge_t, flow_resource_t *);
+nxge_status_t nxge_fflp_config_tcam_enable(p_nxge_t);
+nxge_status_t nxge_fflp_config_tcam_disable(p_nxge_t);
+
+nxge_status_t nxge_fflp_config_hash_lookup_enable(p_nxge_t);
+nxge_status_t nxge_fflp_config_hash_lookup_disable(p_nxge_t);
+
+nxge_status_t nxge_fflp_config_llc_snap_enable(p_nxge_t);
+nxge_status_t nxge_fflp_config_llc_snap_disable(p_nxge_t);
+
+nxge_status_t nxge_logical_mac_assign_rdc_table(p_nxge_t, uint8_t);
+nxge_status_t nxge_fflp_config_vlan_table(p_nxge_t, uint16_t);
+
+nxge_status_t nxge_fflp_set_hash1(p_nxge_t, uint32_t);
+
+nxge_status_t nxge_fflp_set_hash2(p_nxge_t, uint16_t);
+
+nxge_status_t nxge_fflp_init_hostinfo(p_nxge_t);
+
+void nxge_handle_tcam_fragment_bug(p_nxge_t);
+nxge_status_t nxge_fflp_hw_reset(p_nxge_t);
+nxge_status_t nxge_fflp_handle_sys_errors(p_nxge_t);
+nxge_status_t nxge_zcp_handle_sys_errors(p_nxge_t);
+
+/* nxge_kstats.c */
+void nxge_init_statsp(p_nxge_t);
+void nxge_setup_kstats(p_nxge_t);
+void nxge_destroy_kstats(p_nxge_t);
+int nxge_port_kstat_update(kstat_t *, int);
+void nxge_save_cntrs(p_nxge_t);
+
+int nxge_m_stat(void *arg, uint_t, uint64_t *);
+
+/* nxge_hw.c */
+void
+nxge_hw_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *);
+void nxge_loopback_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *);
+void nxge_global_reset(p_nxge_t);
+uint_t nxge_intr(void *, void *);
+void nxge_intr_enable(p_nxge_t);
+void nxge_intr_disable(p_nxge_t);
+void nxge_hw_blank(void *arg, time_t, uint_t);
+void nxge_hw_id_init(p_nxge_t);
+void nxge_hw_init_niu_common(p_nxge_t);
+void nxge_intr_hw_enable(p_nxge_t);
+void nxge_intr_hw_disable(p_nxge_t);
+void nxge_hw_stop(p_nxge_t);
+void nxge_global_reset(p_nxge_t);
+void nxge_check_hw_state(p_nxge_t);
+
+void nxge_rxdma_channel_put64(nxge_os_acc_handle_t,
+ void *, uint32_t, uint16_t,
+ uint64_t);
+uint64_t nxge_rxdma_channel_get64(nxge_os_acc_handle_t, void *,
+ uint32_t, uint16_t);
+
+
+void nxge_get32(p_nxge_t, p_mblk_t);
+void nxge_put32(p_nxge_t, p_mblk_t);
+
+void nxge_hw_set_mac_modes(p_nxge_t);
+
+/* nxge_send.c. */
+uint_t nxge_reschedule(caddr_t);
+
+/* nxge_rxdma.c */
+nxge_status_t nxge_rxdma_cfg_rdcgrp_default_rdc(p_nxge_t,
+ uint8_t, uint8_t);
+
+nxge_status_t nxge_rxdma_cfg_port_default_rdc(p_nxge_t,
+ uint8_t, uint8_t);
+nxge_status_t nxge_rxdma_cfg_rcr_threshold(p_nxge_t, uint8_t,
+ uint16_t);
+nxge_status_t nxge_rxdma_cfg_rcr_timeout(p_nxge_t, uint8_t,
+ uint16_t, uint8_t);
+
+/* nxge_ndd.c */
+void nxge_get_param_soft_properties(p_nxge_t);
+void nxge_copy_hw_default_to_param(p_nxge_t);
+void nxge_copy_param_hw_to_config(p_nxge_t);
+void nxge_setup_param(p_nxge_t);
+void nxge_init_param(p_nxge_t);
+void nxge_destroy_param(p_nxge_t);
+boolean_t nxge_check_rxdma_rdcgrp_member(p_nxge_t, uint8_t, uint8_t);
+boolean_t nxge_check_rxdma_port_member(p_nxge_t, uint8_t);
+boolean_t nxge_check_rdcgrp_port_member(p_nxge_t, uint8_t);
+
+boolean_t nxge_check_txdma_port_member(p_nxge_t, uint8_t);
+
+int nxge_param_get_generic(p_nxge_t, queue_t *, mblk_t *, caddr_t);
+int nxge_param_set_generic(p_nxge_t, queue_t *, mblk_t *, char *, caddr_t);
+int nxge_get_default(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+int nxge_set_default(p_nxge_t, queue_t *, p_mblk_t, char *, caddr_t);
+int nxge_nd_get_names(p_nxge_t, queue_t *, p_mblk_t, caddr_t);
+int nxge_mk_mblk_tail_space(p_mblk_t, p_mblk_t *, size_t);
+long nxge_strtol(char *, char **, int);
+boolean_t nxge_param_get_instance(queue_t *, mblk_t *);
+void nxge_param_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *);
+boolean_t nxge_nd_load(caddr_t *, char *, pfi_t, pfi_t, caddr_t);
+void nxge_nd_free(caddr_t *);
+int nxge_nd_getset(p_nxge_t, queue_t *, caddr_t, p_mblk_t);
+
+void nxge_set_lb_normal(p_nxge_t);
+boolean_t nxge_set_lb(p_nxge_t, queue_t *, p_mblk_t);
+
+/* nxge_virtual.c */
+nxge_status_t nxge_cntlops(dev_info_t *, nxge_ctl_enum_t, void *, void *);
+void nxge_common_lock_get(p_nxge_t);
+void nxge_common_lock_free(p_nxge_t);
+
+nxge_status_t nxge_get_config_properties(p_nxge_t);
+void nxge_get_xcvr_properties(p_nxge_t);
+void nxge_init_vlan_config(p_nxge_t);
+void nxge_init_mac_config(p_nxge_t);
+
+
+void nxge_init_logical_devs(p_nxge_t);
+int nxge_init_ldg_intrs(p_nxge_t);
+
+void nxge_set_ldgimgmt(p_nxge_t, uint32_t, boolean_t,
+ uint32_t);
+
+void nxge_init_fzc_txdma_channels(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_txdma_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+nxge_status_t nxge_init_fzc_txdma_port(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel(p_nxge_t, uint16_t,
+ p_rx_rbr_ring_t, p_rx_rcr_ring_t, p_rx_mbox_t);
+
+nxge_status_t nxge_init_fzc_rdc_tbl(p_nxge_t);
+nxge_status_t nxge_init_fzc_rx_common(p_nxge_t);
+nxge_status_t nxge_init_fzc_rxdma_port(p_nxge_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel_pages(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t);
+nxge_status_t nxge_init_fzc_rxdma_channel_red(p_nxge_t,
+ uint16_t, p_rx_rcr_ring_t);
+
+nxge_status_t nxge_init_fzc_rxdma_channel_clrlog(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t);
+
+
+nxge_status_t nxge_init_fzc_txdma_channel_pages(p_nxge_t,
+ uint16_t, p_tx_ring_t);
+
+nxge_status_t nxge_init_fzc_txdma_channel_drr(p_nxge_t, uint16_t,
+ p_tx_ring_t);
+
+nxge_status_t nxge_init_fzc_txdma_port(p_nxge_t);
+
+void nxge_init_fzc_ldg_num(p_nxge_t);
+void nxge_init_fzc_sys_int_data(p_nxge_t);
+void nxge_init_fzc_ldg_int_timer(p_nxge_t);
+nxge_status_t nxge_intr_mask_mgmt_set(p_nxge_t, boolean_t on);
+
+/* MAC functions */
+nxge_status_t nxge_mac_init(p_nxge_t);
+nxge_status_t nxge_link_init(p_nxge_t);
+nxge_status_t nxge_xif_init(p_nxge_t);
+nxge_status_t nxge_pcs_init(p_nxge_t);
+nxge_status_t nxge_serdes_init(p_nxge_t);
+nxge_status_t nxge_n2_serdes_init(p_nxge_t);
+nxge_status_t nxge_neptune_serdes_init(p_nxge_t);
+nxge_status_t nxge_xcvr_find(p_nxge_t);
+nxge_status_t nxge_get_xcvr_type(p_nxge_t);
+nxge_status_t nxge_xcvr_init(p_nxge_t);
+nxge_status_t nxge_tx_mac_init(p_nxge_t);
+nxge_status_t nxge_rx_mac_init(p_nxge_t);
+nxge_status_t nxge_tx_mac_enable(p_nxge_t);
+nxge_status_t nxge_tx_mac_disable(p_nxge_t);
+nxge_status_t nxge_rx_mac_enable(p_nxge_t);
+nxge_status_t nxge_rx_mac_disable(p_nxge_t);
+nxge_status_t nxge_tx_mac_reset(p_nxge_t);
+nxge_status_t nxge_rx_mac_reset(p_nxge_t);
+nxge_status_t nxge_link_intr(p_nxge_t, link_intr_enable_t);
+nxge_status_t nxge_mii_xcvr_init(p_nxge_t);
+nxge_status_t nxge_mii_read(p_nxge_t, uint8_t,
+ uint8_t, uint16_t *);
+nxge_status_t nxge_mii_write(p_nxge_t, uint8_t,
+ uint8_t, uint16_t);
+nxge_status_t nxge_mdio_read(p_nxge_t, uint8_t, uint8_t,
+ uint16_t, uint16_t *);
+nxge_status_t nxge_mdio_write(p_nxge_t, uint8_t,
+ uint8_t, uint16_t, uint16_t);
+nxge_status_t nxge_mii_check(p_nxge_t, mii_bmsr_t,
+ mii_bmsr_t);
+nxge_status_t nxge_add_mcast_addr(p_nxge_t, struct ether_addr *);
+nxge_status_t nxge_del_mcast_addr(p_nxge_t, struct ether_addr *);
+nxge_status_t nxge_set_mac_addr(p_nxge_t, struct ether_addr *);
+nxge_status_t nxge_check_mii_link(p_nxge_t);
+nxge_status_t nxge_check_10g_link(p_nxge_t);
+nxge_status_t nxge_check_serdes_link(p_nxge_t);
+nxge_status_t nxge_check_bcm8704_link(p_nxge_t, boolean_t *);
+void nxge_link_is_down(p_nxge_t);
+void nxge_link_is_up(p_nxge_t);
+nxge_status_t nxge_link_monitor(p_nxge_t, link_mon_enable_t);
+uint32_t crc32_mchash(p_ether_addr_t);
+nxge_status_t nxge_set_promisc(p_nxge_t, boolean_t);
+nxge_status_t nxge_mac_handle_sys_errors(p_nxge_t);
+nxge_status_t nxge_10g_link_led_on(p_nxge_t);
+nxge_status_t nxge_10g_link_led_off(p_nxge_t);
+
+/* espc (sprom) prototypes */
+nxge_status_t nxge_espc_mac_addrs_get(p_nxge_t);
+nxge_status_t nxge_espc_num_macs_get(p_nxge_t, uint8_t *);
+nxge_status_t nxge_espc_num_ports_get(p_nxge_t);
+nxge_status_t nxge_espc_phy_type_get(p_nxge_t);
+
+
+void nxge_debug_msg(p_nxge_t, uint64_t, char *, ...);
+
+uint64_t hv_niu_rx_logical_page_conf(uint64_t, uint64_t,
+ uint64_t, uint64_t);
+#pragma weak hv_niu_rx_logical_page_conf
+
+uint64_t hv_niu_rx_logical_page_info(uint64_t, uint64_t,
+ uint64_t *, uint64_t *);
+#pragma weak hv_niu_rx_logical_page_info
+
+uint64_t hv_niu_tx_logical_page_conf(uint64_t, uint64_t,
+ uint64_t, uint64_t);
+#pragma weak hv_niu_tx_logical_page_conf
+
+uint64_t hv_niu_tx_logical_page_info(uint64_t, uint64_t,
+ uint64_t *, uint64_t *);
+#pragma weak hv_niu_tx_logical_page_info
+
+#ifdef NXGE_DEBUG
+char *nxge_dump_packet(char *, int);
+#endif
+
+#endif /* !_ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_IMPL_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_ipp.h b/usr/src/uts/sun4v/sys/nxge/nxge_ipp.h
new file mode 100644
index 0000000000..80e3a4c1d5
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_ipp.h
@@ -0,0 +1,83 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_IPP_H
+#define _SYS_NXGE_NXGE_IPP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_ipp_hw.h>
+#include <npi_ipp.h>
+
+#define IPP_MAX_PKT_SIZE 0x1FFFF
+#define IPP_MAX_ERR_SHOW 10
+
+typedef struct _ipp_errlog {
+ boolean_t multiple_err;
+ uint16_t dfifo_rd_ptr;
+ uint32_t state_mach;
+ uint16_t ecc_syndrome;
+} ipp_errlog_t, *p_ipp_errlog_t;
+
+typedef struct _nxge_ipp_stats {
+ uint32_t errors;
+ uint32_t inits;
+ uint32_t sop_miss;
+ uint32_t eop_miss;
+ uint32_t dfifo_ue;
+ uint32_t ecc_err_cnt;
+ uint32_t pfifo_perr;
+ uint32_t pfifo_over;
+ uint32_t pfifo_und;
+ uint32_t bad_cs_cnt;
+ uint32_t pkt_dis_cnt;
+ ipp_errlog_t errlog;
+} nxge_ipp_stats_t, *p_nxge_ipp_stats_t;
+
+typedef struct _nxge_ipp {
+ uint32_t config;
+ uint32_t iconfig;
+ ipp_status_t status;
+ uint32_t max_pkt_size;
+ nxge_ipp_stats_t *stat;
+} nxge_ipp_t;
+
+/* IPP prototypes */
+nxge_status_t nxge_ipp_reset(p_nxge_t);
+nxge_status_t nxge_ipp_init(p_nxge_t);
+nxge_status_t nxge_ipp_disable(p_nxge_t);
+nxge_status_t nxge_ipp_handle_sys_errors(p_nxge_t);
+nxge_status_t nxge_ipp_fatal_err_recover(p_nxge_t);
+void nxge_ipp_inject_err(p_nxge_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_IPP_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_ipp_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_ipp_hw.h
new file mode 100644
index 0000000000..9c4d508e1e
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_ipp_hw.h
@@ -0,0 +1,251 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_IPP_HW_H
+#define _SYS_NXGE_NXGE_IPP_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+/* IPP Registers */
+#define IPP_CONFIG_REG 0x000
+#define IPP_DISCARD_PKT_CNT_REG 0x020
+#define IPP_TCP_CKSUM_ERR_CNT_REG 0x028
+#define IPP_ECC_ERR_COUNTER_REG 0x030
+#define IPP_INT_STATUS_REG 0x040
+#define IPP_INT_MASK_REG 0x048
+
+#define IPP_PFIFO_RD_DATA0_REG 0x060
+#define IPP_PFIFO_RD_DATA1_REG 0x068
+#define IPP_PFIFO_RD_DATA2_REG 0x070
+#define IPP_PFIFO_RD_DATA3_REG 0x078
+#define IPP_PFIFO_RD_DATA4_REG 0x080
+#define IPP_PFIFO_WR_DATA0_REG 0x088
+#define IPP_PFIFO_WR_DATA1_REG 0x090
+#define IPP_PFIFO_WR_DATA2_REG 0x098
+#define IPP_PFIFO_WR_DATA3_REG 0x0a0
+#define IPP_PFIFO_WR_DATA4_REG 0x0a8
+#define IPP_PFIFO_RD_PTR_REG 0x0b0
+#define IPP_PFIFO_WR_PTR_REG 0x0b8
+#define IPP_DFIFO_RD_DATA0_REG 0x0c0
+#define IPP_DFIFO_RD_DATA1_REG 0x0c8
+#define IPP_DFIFO_RD_DATA2_REG 0x0d0
+#define IPP_DFIFO_RD_DATA3_REG 0x0d8
+#define IPP_DFIFO_RD_DATA4_REG 0x0e0
+#define IPP_DFIFO_WR_DATA0_REG 0x0e8
+#define IPP_DFIFO_WR_DATA1_REG 0x0f0
+#define IPP_DFIFO_WR_DATA2_REG 0x0f8
+#define IPP_DFIFO_WR_DATA3_REG 0x100
+#define IPP_DFIFO_WR_DATA4_REG 0x108
+#define IPP_DFIFO_RD_PTR_REG 0x110
+#define IPP_DFIFO_WR_PTR_REG 0x118
+#define IPP_STATE_MACHINE_REG 0x120
+#define IPP_CKSUM_STATUS_REG 0x128
+#define IPP_FFLP_CKSUM_INFO_REG 0x130
+#define IPP_DEBUG_SELECT_REG 0x138
+#define IPP_DFIFO_ECC_SYNDROME_REG 0x140
+#define IPP_DFIFO_EOPM_RD_PTR_REG 0x148
+#define IPP_ECC_CTRL_REG 0x150
+
+#define IPP_PORT_OFFSET 0x4000
+#define IPP_PORT0_OFFSET 0
+#define IPP_PORT1_OFFSET 0x8000
+#define IPP_PORT2_OFFSET 0x4000
+#define IPP_PORT3_OFFSET 0xc000
+#define IPP_REG_ADDR(port_num, reg)\
+ ((port_num == 0) ? FZC_IPP + reg : \
+ FZC_IPP + reg + (((port_num % 2) * IPP_PORT_OFFSET) + \
+ ((port_num / 3) * IPP_PORT_OFFSET) + IPP_PORT_OFFSET))
+#define IPP_PORT_ADDR(port_num)\
+ ((port_num == 0) ? FZC_IPP: \
+ FZC_IPP + (((port_num % 2) * IPP_PORT_OFFSET) + \
+ ((port_num / 3) * IPP_PORT_OFFSET) + IPP_PORT_OFFSET))
+
+/* IPP Configuration Register */
+
+#define IPP_SOFT_RESET (1ULL << 31)
+#define IPP_IP_MAX_PKT_BYTES_SHIFT 8
+#define IPP_IP_MAX_PKT_BYTES_MASK 0x1FFFF
+#define IPP_FFLP_CKSUM_INFO_PIO_WR_EN (1 << 7)
+#define IPP_PRE_FIFO_PIO_WR_EN (1 << 6)
+#define IPP_DFIFO_PIO_WR_EN (1 << 5)
+#define IPP_TCP_UDP_CKSUM_EN (1 << 4)
+#define IPP_DROP_BAD_CRC_EN (1 << 3)
+#define IPP_DFIFO_ECC_CORRECT_EN (1 << 2)
+#define IPP_EN (1 << 0)
+
+/* IPP Interrupt Status Registers */
+
+#define IPP_DFIFO_MISSED_SOP (1ULL << 31)
+#define IPP_DFIFO_MISSED_EOP (1 << 30)
+#define IPP_DFIFO_ECC_UNCORR_ERR_MASK 0x3
+#define IPP_DFIFO_ECC_UNCORR_ERR_SHIFT 28
+#define IPP_DFIFO_ECC_CORR_ERR_MASK 0x3
+#define IPP_DFIFO_ECC_CORR_ERR_SHIFT 26
+#define IPP_DFIFO_ECC_ERR_MASK 0x3
+#define IPP_DFIFO_ECC_ERR_SHIFT 24
+#define IPP_DFIFO_NO_ECC_ERR (1 << 23)
+#define IPP_DFIFO_ECC_ERR_ENTRY_INDEX_MASK 0x7FF
+#define IPP_DFIFO_ECC_ERR_ENTRY_INDEX_SHIFT 12
+#define IPP_PRE_FIFO_PERR (1 << 11)
+#define IPP_ECC_ERR_CNT_MAX (1 << 10)
+#define IPP_PRE_FIFO_PERR_ENTRY_INDEX_MASK 0x3F
+#define IPP_PRE_FIFO_PERR_ENTRY_INDEX_SHIFT 4
+#define IPP_PRE_FIFO_OVERRUN (1 << 3)
+#define IPP_PRE_FIFO_UNDERRUN (1 << 2)
+#define IPP_BAD_TCPIP_CHKSUM_CNT_MAX (1 << 1)
+#define IPP_PKT_DISCARD_CNT_MAX (1 << 0)
+
+#define IPP_P0_P1_DFIFO_ENTRIES 2048
+#define IPP_P2_P3_DFIFO_ENTRIES 1024
+#define IPP_NIU_DFIFO_ENTRIES 1024
+
+typedef union _ipp_status {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t dfifo_missed_sop : 1;
+ uint32_t dfifo_missed_eop : 1;
+ uint32_t dfifo_uncorr_ecc_err : 2;
+ uint32_t dfifo_corr_ecc_err : 2;
+ uint32_t dfifo_ecc_err : 2;
+ uint32_t dfifo_no_ecc_err : 1;
+ uint32_t dfifo_ecc_err_idx : 11;
+ uint32_t pre_fifo_perr : 1;
+ uint32_t ecc_err_cnt_ovfl : 1;
+ uint32_t pre_fifo_perr_idx : 6;
+ uint32_t pre_fifo_overrun : 1;
+ uint32_t pre_fifo_underrun : 1;
+ uint32_t bad_cksum_cnt_ovfl : 1;
+ uint32_t pkt_discard_cnt_ovfl : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_discard_cnt_ovfl : 1;
+ uint32_t bad_cksum_cnt_ovfl : 1;
+ uint32_t pre_fifo_underrun : 1;
+ uint32_t pre_fifo_overrun : 1;
+ uint32_t pre_fifo_perr_idx : 6;
+ uint32_t ecc_err_cnt_ovfl : 1;
+ uint32_t pre_fifo_perr : 1;
+ uint32_t dfifo_ecc_err_idx : 11;
+ uint32_t dfifo_no_ecc_err : 1;
+ uint32_t dfifo_ecc_err : 2;
+ uint32_t dfifo_corr_ecc_err : 2;
+ uint32_t dfifo_uncorr_ecc_err : 2;
+ uint32_t dfifo_missed_eop : 1;
+ uint32_t dfifo_missed_sop : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } w0;
+
+#if !defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} ipp_status_t;
+
+typedef union _ipp_ecc_ctrl {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t dis_dbl : 1;
+ uint32_t res3 : 13;
+ uint32_t cor_dbl : 1;
+ uint32_t cor_sng : 1;
+ uint32_t rsvd : 5;
+ uint32_t cor_all : 1;
+ uint32_t res2 : 1;
+ uint32_t cor_1 : 1;
+ uint32_t res1 : 5;
+ uint32_t cor_lst : 1;
+ uint32_t cor_snd : 1;
+ uint32_t cor_fst : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cor_fst : 1;
+ uint32_t cor_snd : 1;
+ uint32_t cor_lst : 1;
+ uint32_t res1 : 5;
+ uint32_t cor_1 : 1;
+ uint32_t res2 : 1;
+ uint32_t cor_all : 1;
+ uint32_t rsvd : 5;
+ uint32_t cor_sng : 1;
+ uint32_t cor_dbl : 1;
+ uint32_t res3 : 13;
+ uint32_t dis_dbl : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } w0;
+
+#if !defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} ipp_ecc_ctrl_t;
+
+
+/* IPP Interrupt Mask Registers */
+
+#define IPP_ECC_ERR_CNT_MAX_INTR_DIS (1 << 7)
+#define IPP_DFIFO_MISSING_EOP_SOP_INTR_DIS (1 << 6)
+#define IPP_DFIFO_ECC_UNCORR_ERR_INTR_DIS (1 << 5)
+#define IPP_PRE_FIFO_PERR_INTR_DIS (1 << 4)
+#define IPP_PRE_FIFO_OVERRUN_INTR_DIS (1 << 3)
+#define IPP_PRE_FIFO_UNDERRUN_INTR_DIS (1 << 2)
+#define IPP_BAD_TCPIP_CKSUM_CNT_INTR_DIS (1 << 1)
+#define IPP_PKT_DISCARD_CNT_INTR_DIS (1 << 0)
+
+#define IPP_RESET_WAIT 10
+
+/* DFIFO RD/WR pointers mask */
+
+#define IPP_XMAC_DFIFO_PTR_MASK 0xFFF
+#define IPP_BMAC_DFIFO_PTR_MASK 0x7FF
+
+#define IPP_ECC_CNT_MASK 0xFF
+#define IPP_BAD_CS_CNT_MASK 0x3FFF
+#define IPP_PKT_DIS_CNT_MASK 0x3FFF
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_IPP_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_mac.h b/usr/src/uts/sun4v/sys/nxge/nxge_mac.h
new file mode 100644
index 0000000000..6e5d39e2e1
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_mac.h
@@ -0,0 +1,239 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_MAC_H
+#define _SYS_NXGE_NXGE_MAC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_mac_hw.h>
+#include <npi_mac.h>
+
+#define NXGE_MTU_DEFAULT_MAX 1522 /* 0x5f2 */
+
+#define NXGE_XMAC_TX_INTRS (ICFG_XMAC_TX_ALL & \
+ ~(ICFG_XMAC_TX_FRAME_XMIT |\
+ ICFG_XMAC_TX_BYTE_CNT_EXP |\
+ ICFG_XMAC_TX_FRAME_CNT_EXP))
+#define NXGE_XMAC_RX_INTRS (ICFG_XMAC_RX_ALL & \
+ ~(ICFG_XMAC_RX_FRAME_RCVD |\
+ ICFG_XMAC_RX_OCT_CNT_EXP |\
+ ICFG_XMAC_RX_HST_CNT1_EXP |\
+ ICFG_XMAC_RX_HST_CNT2_EXP |\
+ ICFG_XMAC_RX_HST_CNT3_EXP |\
+ ICFG_XMAC_RX_HST_CNT4_EXP |\
+ ICFG_XMAC_RX_HST_CNT5_EXP |\
+ ICFG_XMAC_RX_HST_CNT6_EXP |\
+ ICFG_XMAC_RX_BCAST_CNT_EXP |\
+ ICFG_XMAC_RX_MCAST_CNT_EXP |\
+ ICFG_XMAC_RX_HST_CNT7_EXP))
+#define NXGE_BMAC_TX_INTRS (ICFG_BMAC_TX_ALL & \
+ ~(ICFG_BMAC_TX_FRAME_SENT |\
+ ICFG_BMAC_TX_BYTE_CNT_EXP |\
+ ICFG_BMAC_TX_FRAME_CNT_EXP))
+#define NXGE_BMAC_RX_INTRS (ICFG_BMAC_RX_ALL & \
+ ~(ICFG_BMAC_RX_FRAME_RCVD |\
+ ICFG_BMAC_RX_FRAME_CNT_EXP |\
+ ICFG_BMAC_RX_BYTE_CNT_EXP))
+
+/* Common MAC statistics */
+
+typedef struct _nxge_mac_stats {
+ /*
+ * MTU size
+ */
+ uint32_t mac_mtu;
+ uint16_t rev_id;
+
+ /*
+ * Transciever state informations.
+ */
+ uint32_t xcvr_inits;
+ xcvr_inuse_t xcvr_inuse;
+ uint32_t xcvr_portn;
+ uint32_t xcvr_id;
+ uint32_t serdes_inits;
+ uint32_t serdes_portn;
+ uint32_t cap_autoneg;
+ uint32_t cap_10gfdx;
+ uint32_t cap_10ghdx;
+ uint32_t cap_1000fdx;
+ uint32_t cap_1000hdx;
+ uint32_t cap_100T4;
+ uint32_t cap_100fdx;
+ uint32_t cap_100hdx;
+ uint32_t cap_10fdx;
+ uint32_t cap_10hdx;
+ uint32_t cap_asmpause;
+ uint32_t cap_pause;
+
+ /*
+ * Advertised capabilities.
+ */
+ uint32_t adv_cap_autoneg;
+ uint32_t adv_cap_10gfdx;
+ uint32_t adv_cap_10ghdx;
+ uint32_t adv_cap_1000fdx;
+ uint32_t adv_cap_1000hdx;
+ uint32_t adv_cap_100T4;
+ uint32_t adv_cap_100fdx;
+ uint32_t adv_cap_100hdx;
+ uint32_t adv_cap_10fdx;
+ uint32_t adv_cap_10hdx;
+ uint32_t adv_cap_asmpause;
+ uint32_t adv_cap_pause;
+
+ /*
+ * Link partner capabilities.
+ */
+ uint32_t lp_cap_autoneg;
+ uint32_t lp_cap_10gfdx;
+ uint32_t lp_cap_10ghdx;
+ uint32_t lp_cap_1000fdx;
+ uint32_t lp_cap_1000hdx;
+ uint32_t lp_cap_100T4;
+ uint32_t lp_cap_100fdx;
+ uint32_t lp_cap_100hdx;
+ uint32_t lp_cap_10fdx;
+ uint32_t lp_cap_10hdx;
+ uint32_t lp_cap_asmpause;
+ uint32_t lp_cap_pause;
+
+ /*
+ * Physical link statistics.
+ */
+ uint32_t link_T4;
+ uint32_t link_speed;
+ uint32_t link_duplex;
+ uint32_t link_asmpause;
+ uint32_t link_pause;
+ uint32_t link_up;
+
+ /* Promiscous mode */
+ boolean_t promisc;
+} nxge_mac_stats_t;
+
+/* XMAC Statistics */
+
+typedef struct _nxge_xmac_stats {
+ uint32_t tx_frame_cnt;
+ uint32_t tx_underflow_err;
+ uint32_t tx_maxpktsize_err;
+ uint32_t tx_overflow_err;
+ uint32_t tx_fifo_xfr_err;
+ uint64_t tx_byte_cnt;
+ uint32_t rx_frame_cnt;
+ uint32_t rx_underflow_err;
+ uint32_t rx_overflow_err;
+ uint32_t rx_crc_err_cnt;
+ uint32_t rx_len_err_cnt;
+ uint32_t rx_viol_err_cnt;
+ uint64_t rx_byte_cnt;
+ uint64_t rx_hist1_cnt;
+ uint64_t rx_hist2_cnt;
+ uint64_t rx_hist3_cnt;
+ uint64_t rx_hist4_cnt;
+ uint64_t rx_hist5_cnt;
+ uint64_t rx_hist6_cnt;
+ uint64_t rx_hist7_cnt;
+ uint64_t rx_broadcast_cnt;
+ uint64_t rx_mult_cnt;
+ uint32_t rx_frag_cnt;
+ uint32_t rx_frame_align_err_cnt;
+ uint32_t rx_linkfault_err_cnt;
+ uint32_t rx_remotefault_err;
+ uint32_t rx_localfault_err;
+ uint32_t rx_pause_cnt;
+ uint32_t tx_pause_state;
+ uint32_t tx_nopause_state;
+ uint32_t xpcs_deskew_err_cnt;
+ uint32_t xpcs_ln0_symbol_err_cnt;
+ uint32_t xpcs_ln1_symbol_err_cnt;
+ uint32_t xpcs_ln2_symbol_err_cnt;
+ uint32_t xpcs_ln3_symbol_err_cnt;
+} nxge_xmac_stats_t, *p_nxge_xmac_stats_t;
+
+/* BMAC Statistics */
+
+typedef struct _nxge_bmac_stats {
+ uint64_t tx_frame_cnt;
+ uint32_t tx_underrun_err;
+ uint32_t tx_max_pkt_err;
+ uint64_t tx_byte_cnt;
+ uint64_t rx_frame_cnt;
+ uint64_t rx_byte_cnt;
+ uint32_t rx_overflow_err;
+ uint32_t rx_align_err_cnt;
+ uint32_t rx_crc_err_cnt;
+ uint32_t rx_len_err_cnt;
+ uint32_t rx_viol_err_cnt;
+ uint32_t rx_pause_cnt;
+ uint32_t tx_pause_state;
+ uint32_t tx_nopause_state;
+} nxge_bmac_stats_t, *p_nxge_bmac_stats_t;
+
+typedef struct _hash_filter_t {
+ uint_t hash_ref_cnt;
+ uint16_t hash_filter_regs[NMCFILTER_REGS];
+ uint32_t hash_bit_ref_cnt[NMCFILTER_BITS];
+} hash_filter_t, *p_hash_filter_t;
+
+typedef struct _nxge_mac {
+ uint8_t portnum;
+ nxge_port_t porttype;
+ nxge_port_mode_t portmode;
+ nxge_linkchk_mode_t linkchkmode;
+ boolean_t is_jumbo;
+ uint32_t tx_config;
+ uint32_t rx_config;
+ uint32_t xif_config;
+ uint32_t tx_iconfig;
+ uint32_t rx_iconfig;
+ uint32_t ctl_iconfig;
+ uint16_t minframesize;
+ uint16_t maxframesize;
+ uint16_t maxburstsize;
+ uint16_t ctrltype;
+ uint16_t pa_size;
+ uint8_t ipg[3];
+ struct ether_addr mac_addr;
+ struct ether_addr alt_mac_addr[MAC_MAX_ALT_ADDR_ENTRY];
+ struct ether_addr mac_addr_filter;
+ uint16_t hashtab[MAC_MAX_HASH_ENTRY];
+ hostinfo_t hostinfo[MAC_MAX_HOST_INFO_ENTRY];
+ nxge_mac_stats_t *mac_stats;
+ nxge_xmac_stats_t *xmac_stats;
+ nxge_bmac_stats_t *bmac_stats;
+} nxge_mac_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_MAC_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_mac_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_mac_hw.h
new file mode 100644
index 0000000000..5d8cc8f99b
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_mac_hw.h
@@ -0,0 +1,2408 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_MAC_NXGE_MAC_HW_H
+#define _SYS_MAC_NXGE_MAC_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+/* -------------------------- From May's template --------------------------- */
+
+#define NXGE_1GETHERMIN 255
+#define NXGE_ETHERMIN 97
+#define NXGE_MAX_HEADER 250
+
+/* Hardware reset */
+typedef enum {
+ NXGE_TX_DISABLE, /* Disable Tx side */
+ NXGE_RX_DISABLE, /* Disable Rx side */
+ NXGE_CHIP_RESET /* Full chip reset */
+} nxge_reset_t;
+
+#define NXGE_DELAY_AFTER_TXRX 10000 /* 10ms after idling rx/tx */
+#define NXGE_DELAY_AFTER_RESET 1000 /* 1ms after the reset */
+#define NXGE_DELAY_AFTER_EE_RESET 10000 /* 10ms after EEPROM reset */
+#define NXGE_DELAY_AFTER_LINK_RESET 13 /* 13 Us after link reset */
+#define NXGE_LINK_RESETS 8 /* Max PHY resets to wait for */
+ /* linkup */
+
+#define FILTER_M_CTL 0xDCEF1
+#define HASH_BITS 8
+#define NMCFILTER_BITS (1 << HASH_BITS)
+#define HASH_REG_WIDTH 16
+#define BROADCAST_HASH_WORD 0x0f
+#define BROADCAST_HASH_BIT 0x8000
+#define NMCFILTER_REGS NMCFILTER_BITS / HASH_REG_WIDTH
+ /* Number of multicast filter regs */
+
+/* -------------------------------------------------------------------------- */
+
+#define XMAC_PORT_0 0
+#define XMAC_PORT_1 1
+#define BMAC_PORT_0 2
+#define BMAC_PORT_1 3
+
+#define MAC_RESET_WAIT 10 /* usecs */
+
+#define MAC_ADDR_REG_MASK 0xFFFF
+
+/* Network Modes */
+
+typedef enum nxge_network_mode {
+ NET_2_10GE_FIBER = 1,
+ NET_2_10GE_COPPER,
+ NET_1_10GE_FIBER_3_1GE_COPPER,
+ NET_1_10GE_COPPER_3_1GE_COPPER,
+ NET_1_10GE_FIBER_3_1GE_FIBER,
+ NET_1_10GE_COPPER_3_1GE_FIBER,
+ NET_2_1GE_FIBER_2_1GE_COPPER,
+ NET_QGE_FIBER,
+ NET_QGE_COPPER
+} nxge_network_mode_t;
+
+typedef enum nxge_port {
+ PORT_TYPE_XMAC = 1,
+ PORT_TYPE_BMAC
+} nxge_port_t;
+
+typedef enum nxge_port_mode {
+ PORT_1G_COPPER = 1,
+ PORT_1G_FIBER,
+ PORT_10G_COPPER,
+ PORT_10G_FIBER
+} nxge_port_mode_t;
+
+typedef enum nxge_linkchk_mode {
+ LINKCHK_INTR = 1,
+ LINKCHK_TIMER
+} nxge_linkchk_mode_t;
+
+typedef enum {
+ LINK_INTR_STOP,
+ LINK_INTR_START
+} link_intr_enable_t, *link_intr_enable_pt;
+
+typedef enum {
+ LINK_MONITOR_STOP,
+ LINK_MONITOR_START
+} link_mon_enable_t, *link_mon_enable_pt;
+
+typedef enum {
+ NO_XCVR,
+ INT_MII_XCVR,
+ EXT_MII_XCVR,
+ PCS_XCVR,
+ XPCS_XCVR
+} xcvr_inuse_t;
+
+/* macros for port offset calculations */
+
+#define PORT_1_OFFSET 0x6000
+#define PORT_GT_1_OFFSET 0x4000
+
+/* XMAC address macros */
+
+#define XMAC_ADDR_OFFSET_0 0
+#define XMAC_ADDR_OFFSET_1 0x6000
+
+#define XMAC_ADDR_OFFSET(port_num)\
+ (XMAC_ADDR_OFFSET_0 + ((port_num) * PORT_1_OFFSET))
+
+#define XMAC_REG_ADDR(port_num, reg)\
+ (FZC_MAC + (XMAC_ADDR_OFFSET(port_num)) + (reg))
+
+#define XMAC_PORT_ADDR(port_num)\
+ (FZC_MAC + XMAC_ADDR_OFFSET(port_num))
+
+/* BMAC address macros */
+
+#define BMAC_ADDR_OFFSET_2 0x0C000
+#define BMAC_ADDR_OFFSET_3 0x10000
+
+#define BMAC_ADDR_OFFSET(port_num)\
+ (BMAC_ADDR_OFFSET_2 + (((port_num) - 2) * PORT_GT_1_OFFSET))
+
+#define BMAC_REG_ADDR(port_num, reg)\
+ (FZC_MAC + (BMAC_ADDR_OFFSET(port_num)) + (reg))
+
+#define BMAC_PORT_ADDR(port_num)\
+ (FZC_MAC + BMAC_ADDR_OFFSET(port_num))
+
+/* PCS address macros */
+
+#define PCS_ADDR_OFFSET_0 0x04000
+#define PCS_ADDR_OFFSET_1 0x0A000
+#define PCS_ADDR_OFFSET_2 0x0E000
+#define PCS_ADDR_OFFSET_3 0x12000
+
+#define PCS_ADDR_OFFSET(port_num)\
+ ((port_num <= 1) ? \
+ (PCS_ADDR_OFFSET_0 + (port_num) * PORT_1_OFFSET) : \
+ (PCS_ADDR_OFFSET_2 + (((port_num) - 2) * PORT_GT_1_OFFSET)))
+
+#define PCS_REG_ADDR(port_num, reg)\
+ (FZC_MAC + (PCS_ADDR_OFFSET((port_num)) + (reg)))
+
+#define PCS_PORT_ADDR(port_num)\
+ (FZC_MAC + (PCS_ADDR_OFFSET(port_num)))
+
+/* XPCS address macros */
+
+#define XPCS_ADDR_OFFSET_0 0x02000
+#define XPCS_ADDR_OFFSET_1 0x08000
+#define XPCS_ADDR_OFFSET(port_num)\
+ (XPCS_ADDR_OFFSET_0 + ((port_num) * PORT_1_OFFSET))
+
+#define XPCS_ADDR(port_num, reg)\
+ (FZC_MAC + (XPCS_ADDR_OFFSET((port_num)) + (reg)))
+
+#define XPCS_PORT_ADDR(port_num)\
+ (FZC_MAC + (XPCS_ADDR_OFFSET(port_num)))
+
+/* ESR address macro */
+#define ESR_ADDR_OFFSET 0x14000
+#define ESR_ADDR(reg)\
+ (FZC_MAC + (ESR_ADDR_OFFSET) + (reg))
+
+/* MIF address macros */
+#define MIF_ADDR_OFFSET 0x16000
+#define MIF_ADDR(reg)\
+ (FZC_MAC + (MIF_ADDR_OFFSET) + (reg))
+
+/* BMAC registers offset */
+#define BTXMAC_SW_RST_REG 0x000 /* TX MAC software reset */
+#define BRXMAC_SW_RST_REG 0x008 /* RX MAC software reset */
+#define MAC_SEND_PAUSE_REG 0x010 /* send pause command */
+#define BTXMAC_STATUS_REG 0x020 /* TX MAC status */
+#define BRXMAC_STATUS_REG 0x028 /* RX MAC status */
+#define BMAC_CTRL_STAT_REG 0x030 /* MAC control status */
+#define BTXMAC_STAT_MSK_REG 0x040 /* TX MAC mask */
+#define BRXMAC_STAT_MSK_REG 0x048 /* RX MAC mask */
+#define BMAC_C_S_MSK_REG 0x050 /* MAC control mask */
+#define TXMAC_CONFIG_REG 0x060 /* TX MAC config */
+/* cfg register bitmap */
+
+typedef union _btxmac_config_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd : 22;
+ uint32_t hdx_ctrl2 : 1;
+ uint32_t no_fcs : 1;
+ uint32_t hdx_ctrl : 7;
+ uint32_t txmac_enable : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t txmac_enable : 1;
+ uint32_t hdx_ctrl : 7;
+ uint32_t no_fcs : 1;
+ uint32_t hdx_ctrl2 : 1;
+ uint32_t rsrvd : 22;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} btxmac_config_t, *p_btxmac_config_t;
+
+#define RXMAC_CONFIG_REG 0x068 /* RX MAC config */
+
+typedef union _brxmac_config_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd : 20;
+ uint32_t mac_reg_sw_test : 2;
+ uint32_t mac2ipp_pkt_cnt_en : 1;
+ uint32_t rx_crs_extend_en : 1;
+ uint32_t error_chk_dis : 1;
+ uint32_t addr_filter_en : 1;
+ uint32_t hash_filter_en : 1;
+ uint32_t promiscuous_group : 1;
+ uint32_t promiscuous : 1;
+ uint32_t strip_fcs : 1;
+ uint32_t strip_pad : 1;
+ uint32_t rxmac_enable : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rxmac_enable : 1;
+ uint32_t strip_pad : 1;
+ uint32_t strip_fcs : 1;
+ uint32_t promiscuous : 1;
+ uint32_t promiscuous_group : 1;
+ uint32_t hash_filter_en : 1;
+ uint32_t addr_filter_en : 1;
+ uint32_t error_chk_dis : 1;
+ uint32_t rx_crs_extend_en : 1;
+ uint32_t mac2ipp_pkt_cnt_en : 1;
+ uint32_t mac_reg_sw_test : 2;
+ uint32_t rsrvd : 20;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} brxmac_config_t, *p_brxmac_config_t;
+
+#define MAC_CTRL_CONFIG_REG 0x070 /* MAC control config */
+#define MAC_XIF_CONFIG_REG 0x078 /* XIF config */
+
+typedef union _bxif_config_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd2 : 24;
+ uint32_t sel_clk_25mhz : 1;
+ uint32_t led_polarity : 1;
+ uint32_t force_led_on : 1;
+ uint32_t used : 1;
+ uint32_t gmii_mode : 1;
+ uint32_t rsrvd : 1;
+ uint32_t loopback : 1;
+ uint32_t tx_output_en : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t tx_output_en : 1;
+ uint32_t loopback : 1;
+ uint32_t rsrvd : 1;
+ uint32_t gmii_mode : 1;
+ uint32_t used : 1;
+ uint32_t force_led_on : 1;
+ uint32_t led_polarity : 1;
+ uint32_t sel_clk_25mhz : 1;
+ uint32_t rsrvd2 : 24;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} bxif_config_t, *p_bxif_config_t;
+
+#define BMAC_MIN_REG 0x0a0 /* min frame size */
+#define BMAC_MAX_REG 0x0a8 /* max frame size reg */
+#define MAC_PA_SIZE_REG 0x0b0 /* num of preamble bytes */
+#define MAC_CTRL_TYPE_REG 0x0c8 /* type field of MAC ctrl */
+#define BMAC_ADDR0_REG 0x100 /* MAC unique ad0 reg (HI 0) */
+#define BMAC_ADDR1_REG 0x108 /* MAC unique ad1 reg */
+#define BMAC_ADDR2_REG 0x110 /* MAC unique ad2 reg */
+#define BMAC_ADDR3_REG 0x118 /* MAC alt ad0 reg (HI 1) */
+#define BMAC_ADDR4_REG 0x120 /* MAC alt ad0 reg */
+#define BMAC_ADDR5_REG 0x128 /* MAC alt ad0 reg */
+#define BMAC_ADDR6_REG 0x130 /* MAC alt ad1 reg (HI 2) */
+#define BMAC_ADDR7_REG 0x138 /* MAC alt ad1 reg */
+#define BMAC_ADDR8_REG 0x140 /* MAC alt ad1 reg */
+#define BMAC_ADDR9_REG 0x148 /* MAC alt ad2 reg (HI 3) */
+#define BMAC_ADDR10_REG 0x150 /* MAC alt ad2 reg */
+#define BMAC_ADDR11_REG 0x158 /* MAC alt ad2 reg */
+#define BMAC_ADDR12_REG 0x160 /* MAC alt ad3 reg (HI 4) */
+#define BMAC_ADDR13_REG 0x168 /* MAC alt ad3 reg */
+#define BMAC_ADDR14_REG 0x170 /* MAC alt ad3 reg */
+#define BMAC_ADDR15_REG 0x178 /* MAC alt ad4 reg (HI 5) */
+#define BMAC_ADDR16_REG 0x180 /* MAC alt ad4 reg */
+#define BMAC_ADDR17_REG 0x188 /* MAC alt ad4 reg */
+#define BMAC_ADDR18_REG 0x190 /* MAC alt ad5 reg (HI 6) */
+#define BMAC_ADDR19_REG 0x198 /* MAC alt ad5 reg */
+#define BMAC_ADDR20_REG 0x1a0 /* MAC alt ad5 reg */
+#define BMAC_ADDR21_REG 0x1a8 /* MAC alt ad6 reg (HI 7) */
+#define BMAC_ADDR22_REG 0x1b0 /* MAC alt ad6 reg */
+#define BMAC_ADDR23_REG 0x1b8 /* MAC alt ad6 reg */
+#define MAC_FC_ADDR0_REG 0x268 /* FC frame addr0 (HI 0, p3) */
+#define MAC_FC_ADDR1_REG 0x270 /* FC frame addr1 */
+#define MAC_FC_ADDR2_REG 0x278 /* FC frame addr2 */
+#define MAC_ADDR_FILT0_REG 0x298 /* bits [47:32] (HI 0, p2) */
+#define MAC_ADDR_FILT1_REG 0x2a0 /* bits [31:16] */
+#define MAC_ADDR_FILT2_REG 0x2a8 /* bits [15:0] */
+#define MAC_ADDR_FILT12_MASK_REG 0x2b0 /* addr filter 2 & 1 mask */
+#define MAC_ADDR_FILT00_MASK_REG 0x2b8 /* addr filter 0 mask */
+#define MAC_HASH_TBL0_REG 0x2c0 /* hash table 0 reg */
+#define MAC_HASH_TBL1_REG 0x2c8 /* hash table 1 reg */
+#define MAC_HASH_TBL2_REG 0x2d0 /* hash table 2 reg */
+#define MAC_HASH_TBL3_REG 0x2d8 /* hash table 3 reg */
+#define MAC_HASH_TBL4_REG 0x2e0 /* hash table 4 reg */
+#define MAC_HASH_TBL5_REG 0x2e8 /* hash table 5 reg */
+#define MAC_HASH_TBL6_REG 0x2f0 /* hash table 6 reg */
+#define MAC_HASH_TBL7_REG 0x2f8 /* hash table 7 reg */
+#define MAC_HASH_TBL8_REG 0x300 /* hash table 8 reg */
+#define MAC_HASH_TBL9_REG 0x308 /* hash table 9 reg */
+#define MAC_HASH_TBL10_REG 0x310 /* hash table 10 reg */
+#define MAC_HASH_TBL11_REG 0x318 /* hash table 11 reg */
+#define MAC_HASH_TBL12_REG 0x320 /* hash table 12 reg */
+#define MAC_HASH_TBL13_REG 0x328 /* hash table 13 reg */
+#define MAC_HASH_TBL14_REG 0x330 /* hash table 14 reg */
+#define MAC_HASH_TBL15_REG 0x338 /* hash table 15 reg */
+#define RXMAC_FRM_CNT_REG 0x370 /* receive frame counter */
+#define MAC_LEN_ER_CNT_REG 0x378 /* length error counter */
+#define BMAC_AL_ER_CNT_REG 0x380 /* alignment error counter */
+#define BMAC_CRC_ER_CNT_REG 0x388 /* FCS error counter */
+#define BMAC_CD_VIO_CNT_REG 0x390 /* RX code violation err */
+#define BMAC_SM_REG 0x3a0 /* (ro) state machine reg */
+#define BMAC_ALTAD_CMPEN_REG 0x3f8 /* Alt addr compare enable */
+#define BMAC_HOST_INF0_REG 0x400 /* Host info */
+ /* (own da, add filter, fc) */
+#define BMAC_HOST_INF1_REG 0x408 /* Host info (alt ad 0) */
+#define BMAC_HOST_INF2_REG 0x410 /* Host info (alt ad 1) */
+#define BMAC_HOST_INF3_REG 0x418 /* Host info (alt ad 2) */
+#define BMAC_HOST_INF4_REG 0x420 /* Host info (alt ad 3) */
+#define BMAC_HOST_INF5_REG 0x428 /* Host info (alt ad 4) */
+#define BMAC_HOST_INF6_REG 0x430 /* Host info (alt ad 5) */
+#define BMAC_HOST_INF7_REG 0x438 /* Host info (alt ad 6) */
+#define BMAC_HOST_INF8_REG 0x440 /* Host info (hash hit, miss) */
+#define BTXMAC_BYTE_CNT_REG 0x448 /* Tx byte count */
+#define BTXMAC_FRM_CNT_REG 0x450 /* frame count */
+#define BRXMAC_BYTE_CNT_REG 0x458 /* Rx byte count */
+/* x ranges from 0 to 6 (BMAC_MAX_ALT_ADDR_ENTRY - 1) */
+#define BMAC_ALT_ADDR0N_REG_ADDR(x) (BMAC_ADDR3_REG + (x) * 24)
+#define BMAC_ALT_ADDR1N_REG_ADDR(x) (BMAC_ADDR3_REG + 8 + (x) * 24)
+#define BMAC_ALT_ADDR2N_REG_ADDR(x) (BMAC_ADDR3_REG + 0x10 + (x) * 24)
+#define BMAC_HASH_TBLN_REG_ADDR(x) (MAC_HASH_TBL0_REG + (x) * 8)
+#define BMAC_HOST_INFN_REG_ADDR(x) (BMAC_HOST_INF0_REG + (x) * 8)
+
+/* XMAC registers offset */
+#define XTXMAC_SW_RST_REG 0x000 /* XTX MAC soft reset */
+#define XRXMAC_SW_RST_REG 0x008 /* XRX MAC soft reset */
+#define XTXMAC_STATUS_REG 0x020 /* XTX MAC status */
+#define XRXMAC_STATUS_REG 0x028 /* XRX MAC status */
+#define XMAC_CTRL_STAT_REG 0x030 /* Control / Status */
+#define XTXMAC_STAT_MSK_REG 0x040 /* XTX MAC Status mask */
+#define XRXMAC_STAT_MSK_REG 0x048 /* XRX MAC Status mask */
+#define XMAC_C_S_MSK_REG 0x050 /* Control / Status mask */
+#define XMAC_CONFIG_REG 0x060 /* Configuration */
+
+/* xmac config bit fields */
+typedef union _xmac_cfg_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sel_clk_25mhz : 1;
+ uint32_t pcs_bypass : 1;
+ uint32_t xpcs_bypass : 1;
+ uint32_t mii_gmii_mode : 2;
+ uint32_t lfs_disable : 1;
+ uint32_t loopback : 1;
+ uint32_t tx_output_en : 1;
+ uint32_t sel_por_clk_src : 1;
+ uint32_t led_polarity : 1;
+ uint32_t force_led_on : 1;
+ uint32_t pass_fctl_frames : 1;
+ uint32_t recv_pause_en : 1;
+ uint32_t mac2ipp_pkt_cnt_en : 1;
+ uint32_t strip_crc : 1;
+ uint32_t addr_filter_en : 1;
+ uint32_t hash_filter_en : 1;
+ uint32_t code_viol_chk_dis : 1;
+ uint32_t reserved_mcast : 1;
+ uint32_t rx_crc_chk_dis : 1;
+ uint32_t error_chk_dis : 1;
+ uint32_t promisc_grp : 1;
+ uint32_t promiscuous : 1;
+ uint32_t rx_mac_enable : 1;
+ uint32_t warning_msg_en : 1;
+ uint32_t used : 3;
+ uint32_t always_no_crc : 1;
+ uint32_t var_min_ipg_en : 1;
+ uint32_t strech_mode : 1;
+ uint32_t tx_enable : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t tx_enable : 1;
+ uint32_t strech_mode : 1;
+ uint32_t var_min_ipg_en : 1;
+ uint32_t always_no_crc : 1;
+ uint32_t used : 3;
+ uint32_t warning_msg_en : 1;
+ uint32_t rx_mac_enable : 1;
+ uint32_t promiscuous : 1;
+ uint32_t promisc_grp : 1;
+ uint32_t error_chk_dis : 1;
+ uint32_t rx_crc_chk_dis : 1;
+ uint32_t reserved_mcast : 1;
+ uint32_t code_viol_chk_dis : 1;
+ uint32_t hash_filter_en : 1;
+ uint32_t addr_filter_en : 1;
+ uint32_t strip_crc : 1;
+ uint32_t mac2ipp_pkt_cnt_en : 1;
+ uint32_t recv_pause_en : 1;
+ uint32_t pass_fctl_frames : 1;
+ uint32_t force_led_on : 1;
+ uint32_t led_polarity : 1;
+ uint32_t sel_por_clk_src : 1;
+ uint32_t tx_output_en : 1;
+ uint32_t loopback : 1;
+ uint32_t lfs_disable : 1;
+ uint32_t mii_gmii_mode : 2;
+ uint32_t xpcs_bypass : 1;
+ uint32_t pcs_bypass : 1;
+ uint32_t sel_clk_25mhz : 1;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xmac_cfg_t, *p_xmac_cfg_t;
+
+#define XMAC_IPG_REG 0x080 /* Inter-Packet-Gap */
+#define XMAC_MIN_REG 0x088 /* min frame size register */
+#define XMAC_MAX_REG 0x090 /* max frame/burst size */
+#define XMAC_ADDR0_REG 0x0a0 /* [47:32] of MAC addr (HI17) */
+#define XMAC_ADDR1_REG 0x0a8 /* [31:16] of MAC addr */
+#define XMAC_ADDR2_REG 0x0b0 /* [15:0] of MAC addr */
+#define XRXMAC_BT_CNT_REG 0x100 /* bytes received / 8 */
+#define XRXMAC_BC_FRM_CNT_REG 0x108 /* good BC frames received */
+#define XRXMAC_MC_FRM_CNT_REG 0x110 /* good MC frames received */
+#define XRXMAC_FRAG_CNT_REG 0x118 /* frag frames rejected */
+#define XRXMAC_HIST_CNT1_REG 0x120 /* 64 bytes frames */
+#define XRXMAC_HIST_CNT2_REG 0x128 /* 65-127 bytes frames */
+#define XRXMAC_HIST_CNT3_REG 0x130 /* 128-255 bytes frames */
+#define XRXMAC_HIST_CNT4_REG 0x138 /* 256-511 bytes frames */
+#define XRXMAC_HIST_CNT5_REG 0x140 /* 512-1023 bytes frames */
+#define XRXMAC_HIST_CNT6_REG 0x148 /* 1024-1522 bytes frames */
+#define XRXMAC_MPSZER_CNT_REG 0x150 /* frames > maxframesize */
+#define XRXMAC_CRC_ER_CNT_REG 0x158 /* frames failed CRC */
+#define XRXMAC_CD_VIO_CNT_REG 0x160 /* frames with code vio */
+#define XRXMAC_AL_ER_CNT_REG 0x168 /* frames with align error */
+#define XTXMAC_FRM_CNT_REG 0x170 /* tx frames */
+#define XTXMAC_BYTE_CNT_REG 0x178 /* tx bytes / 8 */
+#define XMAC_LINK_FLT_CNT_REG 0x180 /* link faults */
+#define XRXMAC_HIST_CNT7_REG 0x188 /* MAC2IPP/>1523 bytes frames */
+#define XMAC_SM_REG 0x1a8 /* State machine */
+#define XMAC_INTERN1_REG 0x1b0 /* internal signals for diag */
+#define XMAC_INTERN2_REG 0x1b8 /* internal signals for diag */
+#define XMAC_ADDR_CMPEN_REG 0x208 /* alt MAC addr check */
+#define XMAC_ADDR3_REG 0x218 /* alt MAC addr 0 (HI 0) */
+#define XMAC_ADDR4_REG 0x220 /* alt MAC addr 0 */
+#define XMAC_ADDR5_REG 0x228 /* alt MAC addr 0 */
+#define XMAC_ADDR6_REG 0x230 /* alt MAC addr 1 (HI 1) */
+#define XMAC_ADDR7_REG 0x238 /* alt MAC addr 1 */
+#define XMAC_ADDR8_REG 0x240 /* alt MAC addr 1 */
+#define XMAC_ADDR9_REG 0x248 /* alt MAC addr 2 (HI 2) */
+#define XMAC_ADDR10_REG 0x250 /* alt MAC addr 2 */
+#define XMAC_ADDR11_REG 0x258 /* alt MAC addr 2 */
+#define XMAC_ADDR12_REG 0x260 /* alt MAC addr 3 (HI 3) */
+#define XMAC_ADDR13_REG 0x268 /* alt MAC addr 3 */
+#define XMAC_ADDR14_REG 0x270 /* alt MAC addr 3 */
+#define XMAC_ADDR15_REG 0x278 /* alt MAC addr 4 (HI 4) */
+#define XMAC_ADDR16_REG 0x280 /* alt MAC addr 4 */
+#define XMAC_ADDR17_REG 0x288 /* alt MAC addr 4 */
+#define XMAC_ADDR18_REG 0x290 /* alt MAC addr 5 (HI 5) */
+#define XMAC_ADDR19_REG 0x298 /* alt MAC addr 5 */
+#define XMAC_ADDR20_REG 0x2a0 /* alt MAC addr 5 */
+#define XMAC_ADDR21_REG 0x2a8 /* alt MAC addr 6 (HI 6) */
+#define XMAC_ADDR22_REG 0x2b0 /* alt MAC addr 6 */
+#define XMAC_ADDR23_REG 0x2b8 /* alt MAC addr 6 */
+#define XMAC_ADDR24_REG 0x2c0 /* alt MAC addr 7 (HI 7) */
+#define XMAC_ADDR25_REG 0x2c8 /* alt MAC addr 7 */
+#define XMAC_ADDR26_REG 0x2d0 /* alt MAC addr 7 */
+#define XMAC_ADDR27_REG 0x2d8 /* alt MAC addr 8 (HI 8) */
+#define XMAC_ADDR28_REG 0x2e0 /* alt MAC addr 8 */
+#define XMAC_ADDR29_REG 0x2e8 /* alt MAC addr 8 */
+#define XMAC_ADDR30_REG 0x2f0 /* alt MAC addr 9 (HI 9) */
+#define XMAC_ADDR31_REG 0x2f8 /* alt MAC addr 9 */
+#define XMAC_ADDR32_REG 0x300 /* alt MAC addr 9 */
+#define XMAC_ADDR33_REG 0x308 /* alt MAC addr 10 (HI 10) */
+#define XMAC_ADDR34_REG 0x310 /* alt MAC addr 10 */
+#define XMAC_ADDR35_REG 0x318 /* alt MAC addr 10 */
+#define XMAC_ADDR36_REG 0x320 /* alt MAC addr 11 (HI 11) */
+#define XMAC_ADDR37_REG 0x328 /* alt MAC addr 11 */
+#define XMAC_ADDR38_REG 0x330 /* alt MAC addr 11 */
+#define XMAC_ADDR39_REG 0x338 /* alt MAC addr 12 (HI 12) */
+#define XMAC_ADDR40_REG 0x340 /* alt MAC addr 12 */
+#define XMAC_ADDR41_REG 0x348 /* alt MAC addr 12 */
+#define XMAC_ADDR42_REG 0x350 /* alt MAC addr 13 (HI 13) */
+#define XMAC_ADDR43_REG 0x358 /* alt MAC addr 13 */
+#define XMAC_ADDR44_REG 0x360 /* alt MAC addr 13 */
+#define XMAC_ADDR45_REG 0x368 /* alt MAC addr 14 (HI 14) */
+#define XMAC_ADDR46_REG 0x370 /* alt MAC addr 14 */
+#define XMAC_ADDR47_REG 0x378 /* alt MAC addr 14 */
+#define XMAC_ADDR48_REG 0x380 /* alt MAC addr 15 (HI 15) */
+#define XMAC_ADDR49_REG 0x388 /* alt MAC addr 15 */
+#define XMAC_ADDR50_REG 0x390 /* alt MAC addr 15 */
+#define XMAC_ADDR_FILT0_REG 0x818 /* [47:32] addr filter (HI18) */
+#define XMAC_ADDR_FILT1_REG 0x820 /* [31:16] of addr filter */
+#define XMAC_ADDR_FILT2_REG 0x828 /* [15:0] of addr filter */
+#define XMAC_ADDR_FILT12_MASK_REG 0x830 /* addr filter 2 & 1 mask */
+#define XMAC_ADDR_FILT0_MASK_REG 0x838 /* addr filter 0 mask */
+#define XMAC_HASH_TBL0_REG 0x840 /* hash table 0 reg */
+#define XMAC_HASH_TBL1_REG 0x848 /* hash table 1 reg */
+#define XMAC_HASH_TBL2_REG 0x850 /* hash table 2 reg */
+#define XMAC_HASH_TBL3_REG 0x858 /* hash table 3 reg */
+#define XMAC_HASH_TBL4_REG 0x860 /* hash table 4 reg */
+#define XMAC_HASH_TBL5_REG 0x868 /* hash table 5 reg */
+#define XMAC_HASH_TBL6_REG 0x870 /* hash table 6 reg */
+#define XMAC_HASH_TBL7_REG 0x878 /* hash table 7 reg */
+#define XMAC_HASH_TBL8_REG 0x880 /* hash table 8 reg */
+#define XMAC_HASH_TBL9_REG 0x888 /* hash table 9 reg */
+#define XMAC_HASH_TBL10_REG 0x890 /* hash table 10 reg */
+#define XMAC_HASH_TBL11_REG 0x898 /* hash table 11 reg */
+#define XMAC_HASH_TBL12_REG 0x8a0 /* hash table 12 reg */
+#define XMAC_HASH_TBL13_REG 0x8a8 /* hash table 13 reg */
+#define XMAC_HASH_TBL14_REG 0x8b0 /* hash table 14 reg */
+#define XMAC_HASH_TBL15_REG 0x8b8 /* hash table 15 reg */
+#define XMAC_HOST_INF0_REG 0x900 /* Host info 0 (alt ad 0) */
+#define XMAC_HOST_INF1_REG 0x908 /* Host info 1 (alt ad 1) */
+#define XMAC_HOST_INF2_REG 0x910 /* Host info 2 (alt ad 2) */
+#define XMAC_HOST_INF3_REG 0x918 /* Host info 3 (alt ad 3) */
+#define XMAC_HOST_INF4_REG 0x920 /* Host info 4 (alt ad 4) */
+#define XMAC_HOST_INF5_REG 0x928 /* Host info 5 (alt ad 5) */
+#define XMAC_HOST_INF6_REG 0x930 /* Host info 6 (alt ad 6) */
+#define XMAC_HOST_INF7_REG 0x938 /* Host info 7 (alt ad 7) */
+#define XMAC_HOST_INF8_REG 0x940 /* Host info 8 (alt ad 8) */
+#define XMAC_HOST_INF9_REG 0x948 /* Host info 9 (alt ad 9) */
+#define XMAC_HOST_INF10_REG 0x950 /* Host info 10 (alt ad 10) */
+#define XMAC_HOST_INF11_REG 0x958 /* Host info 11 (alt ad 11) */
+#define XMAC_HOST_INF12_REG 0x960 /* Host info 12 (alt ad 12) */
+#define XMAC_HOST_INF13_REG 0x968 /* Host info 13 (alt ad 13) */
+#define XMAC_HOST_INF14_REG 0x970 /* Host info 14 (alt ad 14) */
+#define XMAC_HOST_INF15_REG 0x978 /* Host info 15 (alt ad 15) */
+#define XMAC_HOST_INF16_REG 0x980 /* Host info 16 (hash hit) */
+#define XMAC_HOST_INF17_REG 0x988 /* Host info 17 (own da) */
+#define XMAC_HOST_INF18_REG 0x990 /* Host info 18 (filter hit) */
+#define XMAC_HOST_INF19_REG 0x998 /* Host info 19 (fc hit) */
+#define XMAC_PA_DATA0_REG 0xb80 /* preamble [31:0] */
+#define XMAC_PA_DATA1_REG 0xb88 /* preamble [63:32] */
+#define XMAC_DEBUG_SEL_REG 0xb90 /* debug select */
+#define XMAC_TRAINING_VECT_REG 0xb98 /* training vector */
+/* x ranges from 0 to 15 (XMAC_MAX_ALT_ADDR_ENTRY - 1) */
+#define XMAC_ALT_ADDR0N_REG_ADDR(x) (XMAC_ADDR3_REG + (x) * 24)
+#define XMAC_ALT_ADDR1N_REG_ADDR(x) (XMAC_ADDR3_REG + 8 + (x) * 24)
+#define XMAC_ALT_ADDR2N_REG_ADDR(x) (XMAC_ADDR3_REG + 16 + (x) * 24)
+#define XMAC_HASH_TBLN_REG_ADDR(x) (XMAC_HASH_TBL0_REG + (x) * 8)
+#define XMAC_HOST_INFN_REG_ADDR(x) (XMAC_HOST_INF0_REG + (x) * 8)
+
+/* MIF registers offset */
+#define MIF_BB_MDC_REG 0 /* MIF bit-bang clock */
+#define MIF_BB_MDO_REG 0x008 /* MIF bit-bang data */
+#define MIF_BB_MDO_EN_REG 0x010 /* MIF bit-bang output en */
+#define MIF_OUTPUT_FRAME_REG 0x018 /* MIF frame/output reg */
+#define MIF_CONFIG_REG 0x020 /* MIF config reg */
+#define MIF_POLL_STATUS_REG 0x028 /* MIF poll status reg */
+#define MIF_POLL_MASK_REG 0x030 /* MIF poll mask reg */
+#define MIF_STATE_MACHINE_REG 0x038 /* MIF state machine reg */
+#define MIF_STATUS_REG 0x040 /* MIF status reg */
+#define MIF_MASK_REG 0x048 /* MIF mask reg */
+
+
+/* PCS registers offset */
+#define PCS_MII_CTRL_REG 0 /* PCS MII control reg */
+#define PCS_MII_STATUS_REG 0x008 /* PCS MII status reg */
+#define PCS_MII_ADVERT_REG 0x010 /* PCS MII advertisement */
+#define PCS_MII_LPA_REG 0x018 /* link partner ability */
+#define PCS_CONFIG_REG 0x020 /* PCS config reg */
+#define PCS_STATE_MACHINE_REG 0x028 /* PCS state machine */
+#define PCS_INTR_STATUS_REG 0x030 /* PCS interrupt status */
+#define PCS_DATAPATH_MODE_REG 0x0a0 /* datapath mode reg */
+#define PCS_PACKET_COUNT_REG 0x0c0 /* PCS packet counter */
+
+#define XPCS_CTRL_1_REG 0 /* Control */
+#define XPCS_STATUS_1_REG 0x008
+#define XPCS_DEV_ID_REG 0x010 /* 32bits IEEE manufacture ID */
+#define XPCS_SPEED_ABILITY_REG 0x018
+#define XPCS_DEV_IN_PKG_REG 0x020
+#define XPCS_CTRL_2_REG 0x028
+#define XPCS_STATUS_2_REG 0x030
+#define XPCS_PKG_ID_REG 0x038 /* Package ID */
+#define XPCS_STATUS_REG 0x040
+#define XPCS_TEST_CTRL_REG 0x048
+#define XPCS_CFG_VENDOR_1_REG 0x050
+#define XPCS_DIAG_VENDOR_2_REG 0x058
+#define XPCS_MASK_1_REG 0x060
+#define XPCS_PKT_CNTR_REG 0x068
+#define XPCS_TX_STATE_MC_REG 0x070
+#define XPCS_DESKEW_ERR_CNTR_REG 0x078
+#define XPCS_SYM_ERR_CNTR_L0_L1_REG 0x080
+#define XPCS_SYM_ERR_CNTR_L2_L3_REG 0x088
+#define XPCS_TRAINING_VECTOR_REG 0x090
+
+/* ESR registers offset */
+#define ESR_RESET_REG 0
+#define ESR_CONFIG_REG 0x008
+#define ESR_0_PLL_CONFIG_REG 0x010
+#define ESR_0_CONTROL_REG 0x018
+#define ESR_0_TEST_CONFIG_REG 0x020
+#define ESR_1_PLL_CONFIG_REG 0x028
+#define ESR_1_CONTROL_REG 0x030
+#define ESR_1_TEST_CONFIG_REG 0x038
+#define ESR_ENET_RGMII_CFG_REG 0x040
+#define ESR_INTERNAL_SIGNALS_REG 0x800
+#define ESR_DEBUG_SEL_REG 0x808
+
+
+/* Reset Register */
+#define MAC_SEND_PAUSE_TIME_MASK 0x0000FFFF /* value of pause time */
+#define MAC_SEND_PAUSE_SEND 0x00010000 /* send pause flow ctrl */
+
+/* Tx MAC Status Register */
+#define MAC_TX_FRAME_XMIT 0x00000001 /* successful tx frame */
+#define MAC_TX_UNDERRUN 0x00000002 /* starvation in xmit */
+#define MAC_TX_MAX_PACKET_ERR 0x00000004 /* TX frame exceeds max */
+#define MAC_TX_BYTE_CNT_EXP 0x00000400 /* TX byte cnt overflow */
+#define MAC_TX_FRAME_CNT_EXP 0x00000800 /* Tx frame cnt overflow */
+
+/* Rx MAC Status Register */
+#define MAC_RX_FRAME_RECV 0x00000001 /* successful rx frame */
+#define MAC_RX_OVERFLOW 0x00000002 /* RX FIFO overflow */
+#define MAC_RX_FRAME_COUNT 0x00000004 /* rx frame cnt rollover */
+#define MAC_RX_ALIGN_ERR 0x00000008 /* alignment err rollover */
+#define MAC_RX_CRC_ERR 0x00000010 /* crc error cnt rollover */
+#define MAC_RX_LEN_ERR 0x00000020 /* length err cnt rollover */
+#define MAC_RX_VIOL_ERR 0x00000040 /* code vio err rollover */
+#define MAC_RX_BYTE_CNT_EXP 0x00000080 /* RX MAC byte rollover */
+
+/* MAC Control Status Register */
+#define MAC_CTRL_PAUSE_RECEIVED 0x00000001 /* successful pause frame */
+#define MAC_CTRL_PAUSE_STATE 0x00000002 /* notpause-->pause */
+#define MAC_CTRL_NOPAUSE_STATE 0x00000004 /* pause-->notpause */
+#define MAC_CTRL_PAUSE_TIME_MASK 0xFFFF0000 /* value of pause time */
+#define MAC_CTRL_PAUSE_TIME_SHIFT 16
+
+/* Tx MAC Configuration Register */
+#define MAC_TX_CFG_TXMAC_ENABLE 0x00000001 /* enable TX MAC. */
+#define MAC_TX_CFG_NO_FCS 0x00000100 /* TX not generate CRC */
+
+/* Rx MAC Configuration Register */
+#define MAC_RX_CFG_RXMAC_ENABLE 0x00000001 /* enable RX MAC */
+#define MAC_RX_CFG_STRIP_PAD 0x00000002 /* not supported, set to 0 */
+#define MAC_RX_CFG_STRIP_FCS 0x00000004 /* strip last 4bytes (CRC) */
+#define MAC_RX_CFG_PROMISC 0x00000008 /* promisc mode enable */
+#define MAC_RX_CFG_PROMISC_GROUP 0x00000010 /* accept all MC frames */
+#define MAC_RX_CFG_HASH_FILTER_EN 0x00000020 /* use hash table */
+#define MAC_RX_CFG_ADDR_FILTER_EN 0x00000040 /* use address filter */
+#define MAC_RX_CFG_DISABLE_DISCARD 0x00000080 /* do not set abort bit */
+#define MAC_RX_MAC2IPP_PKT_CNT_EN 0x00000200 /* rx pkt cnt -> BMAC-IPP */
+#define MAC_RX_MAC_REG_RW_TEST_MASK 0x00000c00 /* BMAC reg RW test */
+#define MAC_RX_MAC_REG_RW_TEST_SHIFT 10
+
+/* MAC Control Configuration Register */
+#define MAC_CTRL_CFG_SEND_PAUSE_EN 0x00000001 /* send pause flow ctrl */
+#define MAC_CTRL_CFG_RECV_PAUSE_EN 0x00000002 /* receive pause flow ctrl */
+#define MAC_CTRL_CFG_PASS_CTRL 0x00000004 /* accept MAC ctrl pkts */
+
+/* MAC XIF Configuration Register */
+#define MAC_XIF_TX_OUTPUT_EN 0x00000001 /* enable Tx output driver */
+#define MAC_XIF_MII_INT_LOOPBACK 0x00000002 /* loopback GMII xmit data */
+#define MAC_XIF_GMII_MODE 0x00000008 /* operates with GMII clks */
+#define MAC_XIF_LINK_LED 0x00000020 /* LINKLED# active (low) */
+#define MAC_XIF_LED_POLARITY 0x00000040 /* LED polarity */
+#define MAC_XIF_SEL_CLK_25MHZ 0x00000080 /* Select 10/100Mbps */
+
+/* MAC IPG Registers */
+#define BMAC_MIN_FRAME_MASK 0x3FF /* 10-bit reg */
+
+/* MAC Max Frame Size Register */
+#define BMAC_MAX_BURST_MASK 0x3FFF0000 /* max burst size [30:16] */
+#define BMAC_MAX_BURST_SHIFT 16
+#define BMAC_MAX_FRAME_MASK 0x00007FFF /* max frame size [14:0] */
+#define BMAC_MAX_FRAME_SHIFT 0
+
+/* MAC Preamble size register */
+#define BMAC_PA_SIZE_MASK 0x000003FF
+ /* # of preable bytes TxMAC sends at the beginning of each frame */
+
+/*
+ * mac address registers:
+ * register contains comparison
+ * -------- -------- ----------
+ * 0 16 MSB of primary MAC addr [47:32] of DA field
+ * 1 16 middle bits "" [31:16] of DA field
+ * 2 16 LSB "" [15:0] of DA field
+ * 3*x 16MSB of alt MAC addr 1-7 [47:32] of DA field
+ * 4*x 16 middle bits "" [31:16]
+ * 5*x 16 LSB "" [15:0]
+ * 42 16 MSB of MAC CTRL addr [47:32] of DA.
+ * 43 16 middle bits "" [31:16]
+ * 44 16 LSB "" [15:0]
+ * MAC CTRL addr must be the reserved multicast addr for MAC CTRL frames.
+ * if there is a match, MAC will set the bit for alternative address
+ * filter pass [15]
+ *
+ * here is the map of registers given MAC address notation: a:b:c:d:e:f
+ * ab cd ef
+ * primary addr reg 2 reg 1 reg 0
+ * alt addr 1 reg 5 reg 4 reg 3
+ * alt addr x reg 5*x reg 4*x reg 3*x
+ * | | | |
+ * | | | |
+ * alt addr 7 reg 23 reg 22 reg 21
+ * ctrl addr reg 44 reg 43 reg 42
+ */
+
+#define BMAC_ALT_ADDR_BASE 0x118
+#define BMAC_MAX_ALT_ADDR_ENTRY 7 /* 7 alternate MAC addr */
+
+/* hash table registers */
+#define MAC_MAX_HASH_ENTRY 16
+
+/* 27-bit register has the current state for key state machines in the MAC */
+#define MAC_SM_RLM_MASK 0x07800000
+#define MAC_SM_RLM_SHIFT 23
+#define MAC_SM_RX_FC_MASK 0x00700000
+#define MAC_SM_RX_FC_SHIFT 20
+#define MAC_SM_TLM_MASK 0x000F0000
+#define MAC_SM_TLM_SHIFT 16
+#define MAC_SM_ENCAP_SM_MASK 0x0000F000
+#define MAC_SM_ENCAP_SM_SHIFT 12
+#define MAC_SM_TX_REQ_MASK 0x00000C00
+#define MAC_SM_TX_REQ_SHIFT 10
+#define MAC_SM_TX_FC_MASK 0x000003C0
+#define MAC_SM_TX_FC_SHIFT 6
+#define MAC_SM_FIFO_WRITE_SEL_MASK 0x00000038
+#define MAC_SM_FIFO_WRITE_SEL_SHIFT 3
+#define MAC_SM_TX_FIFO_EMPTY_MASK 0x00000007
+#define MAC_SM_TX_FIFO_EMPTY_SHIFT 0
+
+#define BMAC_ADDR0_CMPEN 0x00000001
+#define BMAC_ADDRN_CMPEN(x) (BMAC_ADDR0_CMP_EN << (x))
+
+/* MAC Host Info Table Registers */
+#define BMAC_MAX_HOST_INFO_ENTRY 9 /* 9 host entries */
+
+/*
+ * ********************* XMAC registers *********************************
+ */
+
+/* Reset Register */
+#define XTXMAC_SOFT_RST 0x00000001 /* XTX MAC software reset */
+#define XTXMAC_REG_RST 0x00000002 /* XTX MAC registers reset */
+#define XRXMAC_SOFT_RST 0x00000001 /* XRX MAC software reset */
+#define XRXMAC_REG_RST 0x00000002 /* XRX MAC registers reset */
+
+/* XTX MAC Status Register */
+#define XMAC_TX_FRAME_XMIT 0x00000001 /* successful tx frame */
+#define XMAC_TX_UNDERRUN 0x00000002 /* starvation in xmit */
+#define XMAC_TX_MAX_PACKET_ERR 0x00000004 /* XTX frame exceeds max */
+#define XMAC_TX_OVERFLOW 0x00000008 /* XTX byte cnt overflow */
+#define XMAC_TX_FIFO_XFR_ERR 0x00000010 /* xtlm state mach error */
+#define XMAC_TX_BYTE_CNT_EXP 0x00000400 /* XTX byte cnt overflow */
+#define XMAC_TX_FRAME_CNT_EXP 0x00000800 /* XTX frame cnt overflow */
+
+/* XRX MAC Status Register */
+#define XMAC_RX_FRAME_RCVD 0x00000001 /* successful rx frame */
+#define XMAC_RX_OVERFLOW 0x00000002 /* RX FIFO overflow */
+#define XMAC_RX_UNDERFLOW 0x00000004 /* RX FIFO underrun */
+#define XMAC_RX_CRC_ERR_CNT_EXP 0x00000008 /* crc error cnt rollover */
+#define XMAC_RX_LEN_ERR_CNT_EXP 0x00000010 /* length err cnt rollover */
+#define XMAC_RX_VIOL_ERR_CNT_EXP 0x00000020 /* code vio err rollover */
+#define XMAC_RX_OCT_CNT_EXP 0x00000040 /* XRX MAC byte rollover */
+#define XMAC_RX_HST_CNT1_EXP 0x00000080 /* XRX MAC hist1 rollover */
+#define XMAC_RX_HST_CNT2_EXP 0x00000100 /* XRX MAC hist2 rollover */
+#define XMAC_RX_HST_CNT3_EXP 0x00000200 /* XRX MAC hist3 rollover */
+#define XMAC_RX_HST_CNT4_EXP 0x00000400 /* XRX MAC hist4 rollover */
+#define XMAC_RX_HST_CNT5_EXP 0x00000800 /* XRX MAC hist5 rollover */
+#define XMAC_RX_HST_CNT6_EXP 0x00001000 /* XRX MAC hist6 rollover */
+#define XMAC_RX_BCAST_CNT_EXP 0x00002000 /* XRX BC cnt rollover */
+#define XMAC_RX_MCAST_CNT_EXP 0x00004000 /* XRX MC cnt rollover */
+#define XMAC_RX_FRAG_CNT_EXP 0x00008000 /* fragment cnt rollover */
+#define XMAC_RX_ALIGNERR_CNT_EXP 0x00010000 /* framealign err rollover */
+#define XMAC_RX_LINK_FLT_CNT_EXP 0x00020000 /* link fault cnt rollover */
+#define XMAC_RX_REMOTE_FLT_DET 0x00040000 /* Remote Fault detected */
+#define XMAC_RX_LOCAL_FLT_DET 0x00080000 /* Local Fault detected */
+#define XMAC_RX_HST_CNT7_EXP 0x00100000 /* XRX MAC hist7 rollover */
+
+
+#define XMAC_CTRL_PAUSE_RCVD 0x00000001 /* successful pause frame */
+#define XMAC_CTRL_PAUSE_STATE 0x00000002 /* notpause-->pause */
+#define XMAC_CTRL_NOPAUSE_STATE 0x00000004 /* pause-->notpause */
+#define XMAC_CTRL_PAUSE_TIME_MASK 0xFFFF0000 /* value of pause time */
+#define XMAC_CTRL_PAUSE_TIME_SHIFT 16
+
+/* XMAC Configuration Register */
+#define XMAC_CONFIG_TX_BIT_MASK 0x000000ff /* bits [7:0] */
+#define XMAC_CONFIG_RX_BIT_MASK 0x001fff00 /* bits [20:8] */
+#define XMAC_CONFIG_XIF_BIT_MASK 0xffe00000 /* bits [31:21] */
+
+/* XTX MAC config bits */
+#define XMAC_TX_CFG_TX_ENABLE 0x00000001 /* enable XTX MAC */
+#define XMAC_TX_CFG_STRETCH_MD 0x00000002 /* WAN application */
+#define XMAC_TX_CFG_VAR_MIN_IPG_EN 0x00000004 /* Transmit pkts < minpsz */
+#define XMAC_TX_CFG_ALWAYS_NO_CRC 0x00000008 /* No CRC generated */
+
+#define XMAC_WARNING_MSG_ENABLE 0x00000080 /* Sim warning msg enable */
+
+/* XRX MAC config bits */
+#define XMAC_RX_CFG_RX_ENABLE 0x00000100 /* enable XRX MAC */
+#define XMAC_RX_CFG_PROMISC 0x00000200 /* promisc mode enable */
+#define XMAC_RX_CFG_PROMISC_GROUP 0x00000400 /* accept all MC frames */
+#define XMAC_RX_CFG_ERR_CHK_DISABLE 0x00000800 /* do not set abort bit */
+#define XMAC_RX_CFG_CRC_CHK_DISABLE 0x00001000 /* disable CRC logic */
+#define XMAC_RX_CFG_RESERVED_MCAST 0x00002000 /* reserved MCaddr compare */
+#define XMAC_RX_CFG_CD_VIO_CHK 0x00004000 /* rx code violation chk */
+#define XMAC_RX_CFG_HASH_FILTER_EN 0x00008000 /* use hash table */
+#define XMAC_RX_CFG_ADDR_FILTER_EN 0x00010000 /* use alt addr filter */
+#define XMAC_RX_CFG_STRIP_CRC 0x00020000 /* strip last 4bytes (CRC) */
+#define XMAC_RX_MAC2IPP_PKT_CNT_EN 0x00040000 /* histo_cntr7 cnt mode */
+#define XMAC_RX_CFG_RX_PAUSE_EN 0x00080000 /* receive pause flow ctrl */
+#define XMAC_RX_CFG_PASS_FLOW_CTRL 0x00100000 /* accept MAC ctrl pkts */
+
+
+/* MAC transceiver (XIF) configuration registers */
+
+#define XMAC_XIF_FORCE_LED_ON 0x00200000 /* Force Link LED on */
+#define XMAC_XIF_LED_POLARITY 0x00400000 /* LED polarity */
+#define XMAC_XIF_SEL_POR_CLK_SRC 0x00800000 /* Select POR clk src */
+#define XMAC_XIF_TX_OUTPUT_EN 0x01000000 /* enable MII/GMII modes */
+#define XMAC_XIF_LOOPBACK 0x02000000 /* loopback xmac xgmii tx */
+#define XMAC_XIF_LFS_DISABLE 0x04000000 /* disable link fault sig */
+#define XMAC_XIF_MII_MODE_MASK 0x18000000 /* MII/GMII/XGMII mode */
+#define XMAC_XIF_MII_MODE_SHIFT 27
+#define XMAC_XIF_XGMII_MODE 0x00
+#define XMAC_XIF_GMII_MODE 0x01
+#define XMAC_XIF_MII_MODE 0x02
+#define XMAC_XIF_ILLEGAL_MODE 0x03
+#define XMAC_XIF_XPCS_BYPASS 0x20000000 /* use external xpcs */
+#define XMAC_XIF_1G_PCS_BYPASS 0x40000000 /* use external pcs */
+#define XMAC_XIF_SEL_CLK_25MHZ 0x80000000 /* 25Mhz clk for 100mbps */
+
+/* IPG register */
+#define XMAC_IPG_VALUE_MASK 0x00000007 /* IPG in XGMII mode */
+#define XMAC_IPG_VALUE_SHIFT 0
+#define XMAC_IPG_VALUE1_MASK 0x0000ff00 /* IPG in GMII/MII mode */
+#define XMAC_IPG_VALUE1_SHIFT 8
+#define XMAC_IPG_STRETCH_RATIO_MASK 0x001f0000
+#define XMAC_IPG_STRETCH_RATIO_SHIFT 16
+#define XMAC_IPG_STRETCH_CONST_MASK 0x00e00000
+#define XMAC_IPG_STRETCH_CONST_SHIFT 21
+
+#define IPG_12_15_BYTE 3
+#define IPG_16_19_BYTE 4
+#define IPG_20_23_BYTE 5
+#define IPG1_12_BYTES 10
+#define IPG1_13_BYTES 11
+#define IPG1_14_BYTES 12
+#define IPG1_15_BYTES 13
+#define IPG1_16_BYTES 14
+
+
+#define XMAC_MIN_TX_FRM_SZ_MASK 0x3ff /* Min tx frame size */
+#define XMAC_MIN_TX_FRM_SZ_SHIFT 0
+#define XMAC_SLOT_TIME_MASK 0x0003fc00 /* slot time */
+#define XMAC_SLOT_TIME_SHIFT 10
+#define XMAC_MIN_RX_FRM_SZ_MASK 0x3ff00000 /* Min rx frame size */
+#define XMAC_MIN_RX_FRM_SZ_SHIFT 20
+#define XMAC_MAX_FRM_SZ_MASK 0x00003fff /* max tx frame size */
+
+/* State Machine Register */
+#define XMAC_SM_TX_LNK_MGMT_MASK 0x00000007
+#define XMAC_SM_TX_LNK_MGMT_SHIFT 0
+#define XMAC_SM_SOP_DETECT 0x00000008
+#define XMAC_SM_LNK_FLT_SIG_MASK 0x00000030
+#define XMAC_SM_LNK_FLT_SIG_SHIFT 4
+#define XMAC_SM_MII_GMII_MD_RX_LNK 0x00000040
+#define XMAC_SM_XGMII_MD_RX_LNK 0x00000080
+#define XMAC_SM_XGMII_ONLY_VAL_SIG 0x00000100
+#define XMAC_SM_ALT_ADR_N_HSH_FN_SIG 0x00000200
+#define XMAC_SM_RXMAC_IPP_STAT_MASK 0x00001c00
+#define XMAC_SM_RXMAC_IPP_STAT_SHIFT 10
+#define XMAC_SM_RXFIFO_WPTR_CLK_MASK 0x007c0000
+#define XMAC_SM_RXFIFO_WPTR_CLK_SHIFT 18
+#define XMAC_SM_RXFIFO_RPTR_CLK_MASK 0x0F800000
+#define XMAC_SM_RXFIFO_RPTR_CLK_SHIFT 23
+#define XMAC_SM_TXFIFO_FULL_CLK 0x10000000
+#define XMAC_SM_TXFIFO_EMPTY_CLK 0x20000000
+#define XMAC_SM_RXFIFO_FULL_CLK 0x40000000
+#define XMAC_SM_RXFIFO_EMPTY_CLK 0x80000000
+
+/* Internal Signals 1 Register */
+#define XMAC_IS1_OPP_TXMAC_STAT_MASK 0x0000000F
+#define XMAC_IS1_OPP_TXMAC_STAT_SHIFT 0
+#define XMAC_IS1_OPP_TXMAC_ABORT 0x00000010
+#define XMAC_IS1_OPP_TXMAC_TAG 0x00000020
+#define XMAC_IS1_OPP_TXMAC_ACK 0x00000040
+#define XMAC_IS1_TXMAC_OPP_REQ 0x00000080
+#define XMAC_IS1_RXMAC_IPP_STAT_MASK 0x0FFFFF00
+#define XMAC_IS1_RXMAC_IPP_STAT_SHIFT 8
+#define XMAC_IS1_RXMAC_IPP_CTRL 0x10000000
+#define XMAC_IS1_RXMAC_IPP_TAG 0x20000000
+#define XMAC_IS1_IPP_RXMAC_REQ 0x40000000
+#define XMAC_IS1_RXMAC_IPP_ACK 0x80000000
+
+/* Internal Signals 2 Register */
+#define XMAC_IS2_TX_HB_TIMER_MASK 0x0000000F
+#define XMAC_IS2_TX_HB_TIMER_SHIFT 0
+#define XMAC_IS2_RX_HB_TIMER_MASK 0x000000F0
+#define XMAC_IS2_RX_HB_TIMER_SHIFT 4
+#define XMAC_IS2_XPCS_RXC_MASK 0x0000FF00
+#define XMAC_IS2_XPCS_RXC_SHIFT 8
+#define XMAC_IS2_XPCS_TXC_MASK 0x00FF0000
+#define XMAC_IS2_XPCS_TXC_SHIFT 16
+#define XMAC_IS2_LOCAL_FLT_OC_SYNC 0x01000000
+#define XMAC_IS2_RMT_FLT_OC_SYNC 0x02000000
+
+/* Register size masking */
+
+#define XTXMAC_FRM_CNT_MASK 0xFFFFFFFF
+#define XTXMAC_BYTE_CNT_MASK 0xFFFFFFFF
+#define XRXMAC_CRC_ER_CNT_MASK 0x000000FF
+#define XRXMAC_MPSZER_CNT_MASK 0x000000FF
+#define XRXMAC_CD_VIO_CNT_MASK 0x000000FF
+#define XRXMAC_BT_CNT_MASK 0xFFFFFFFF
+#define XRXMAC_HIST_CNT1_MASK 0x001FFFFF
+#define XRXMAC_HIST_CNT2_MASK 0x001FFFFF
+#define XRXMAC_HIST_CNT3_MASK 0x000FFFFF
+#define XRXMAC_HIST_CNT4_MASK 0x0007FFFF
+#define XRXMAC_HIST_CNT5_MASK 0x0003FFFF
+#define XRXMAC_HIST_CNT6_MASK 0x0001FFFF
+#define XRXMAC_BC_FRM_CNT_MASK 0x001FFFFF
+#define XRXMAC_MC_FRM_CNT_MASK 0x001FFFFF
+#define XRXMAC_FRAG_CNT_MASK 0x001FFFFF
+#define XRXMAC_AL_ER_CNT_MASK 0x000000FF
+#define XMAC_LINK_FLT_CNT_MASK 0x000000FF
+#define BTXMAC_FRM_CNT_MASK 0x001FFFFF
+#define BTXMAC_BYTE_CNT_MASK 0x07FFFFFF
+#define RXMAC_FRM_CNT_MASK 0x0000FFFF
+#define BRXMAC_BYTE_CNT_MASK 0x07FFFFFF
+#define BMAC_AL_ER_CNT_MASK 0x0000FFFF
+#define MAC_LEN_ER_CNT_MASK 0x0000FFFF
+#define BMAC_CRC_ER_CNT_MASK 0x0000FFFF
+#define BMAC_CD_VIO_CNT_MASK 0x0000FFFF
+#define XMAC_XPCS_DESKEW_ERR_CNT_MASK 0x000000FF
+#define XMAC_XPCS_SYM_ERR_CNT_L0_MASK 0x0000FFFF
+#define XMAC_XPCS_SYM_ERR_CNT_L1_MASK 0xFFFF0000
+#define XMAC_XPCS_SYM_ERR_CNT_L1_SHIFT 16
+#define XMAC_XPCS_SYM_ERR_CNT_L2_MASK 0x0000FFFF
+#define XMAC_XPCS_SYM_ERR_CNT_L3_MASK 0xFFFF0000
+#define XMAC_XPCS_SYM_ERR_CNT_L3_SHIFT 16
+
+/* Alternate MAC address registers */
+#define XMAC_MAX_ALT_ADDR_ENTRY 16 /* 16 alternate MAC addrs */
+
+/* Max / Min parameters for Neptune MAC */
+
+#define MAC_MAX_ALT_ADDR_ENTRY XMAC_MAX_ALT_ADDR_ENTRY
+#define MAC_MAX_HOST_INFO_ENTRY XMAC_MAX_HOST_INFO_ENTRY
+
+/* HostInfo entry for the unique MAC address */
+#define XMAC_UNIQUE_HOST_INFO_ENTRY 17
+#define BMAC_UNIQUE_HOST_INFO_ENTRY 0
+
+/* HostInfo entry for the multicat address */
+#define XMAC_MULTI_HOST_INFO_ENTRY 16
+#define BMAC_MULTI_HOST_INFO_ENTRY 8
+
+/* XMAC Host Info Register */
+typedef union hostinfo {
+
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t reserved2 : 23;
+ uint32_t mac_pref : 1;
+ uint32_t reserved1 : 5;
+ uint32_t rdc_tbl_num : 3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rdc_tbl_num : 3;
+ uint32_t reserved1 : 5;
+ uint32_t mac_pref : 1;
+ uint32_t reserved2 : 23;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+
+} hostinfo_t;
+
+typedef union hostinfo *hostinfo_pt;
+
+#define XMAC_HI_RDC_TBL_NUM_MASK 0x00000007
+#define XMAC_HI_MAC_PREF 0x00000100
+
+#define XMAC_MAX_HOST_INFO_ENTRY 20 /* 20 host entries */
+
+/*
+ * ******************** MIF registers *********************************
+ */
+
+/*
+ * 32-bit register serves as an instruction register when the MIF is
+ * programmed in frame mode. load this register w/ a valid instruction
+ * (as per IEEE 802.3u MII spec). poll this register to check for instruction
+ * execution completion. during a read operation, this register will also
+ * contain the 16-bit data returned by the transceiver. unless specified
+ * otherwise, fields are considered "don't care" when polling for
+ * completion.
+ */
+
+#define MIF_FRAME_START_MASK 0xC0000000 /* start of frame mask */
+#define MIF_FRAME_ST_22 0x40000000 /* STart of frame, Cl 22 */
+#define MIF_FRAME_ST_45 0x00000000 /* STart of frame, Cl 45 */
+#define MIF_FRAME_OPCODE_MASK 0x30000000 /* opcode */
+#define MIF_FRAME_OP_READ_22 0x20000000 /* read OPcode, Cl 22 */
+#define MIF_FRAME_OP_WRITE_22 0x10000000 /* write OPcode, Cl 22 */
+#define MIF_FRAME_OP_ADDR_45 0x00000000 /* addr of reg to access */
+#define MIF_FRAME_OP_READ_45 0x30000000 /* read OPcode, Cl 45 */
+#define MIF_FRAME_OP_WRITE_45 0x10000000 /* write OPcode, Cl 45 */
+#define MIF_FRAME_OP_P_R_I_A_45 0x10000000 /* post-read-inc-addr */
+#define MIF_FRAME_PHY_ADDR_MASK 0x0F800000 /* phy address mask */
+#define MIF_FRAME_PHY_ADDR_SHIFT 23
+#define MIF_FRAME_REG_ADDR_MASK 0x007C0000 /* reg addr in Cl 22 */
+ /* dev addr in Cl 45 */
+#define MIF_FRAME_REG_ADDR_SHIFT 18
+#define MIF_FRAME_TURN_AROUND_MSB 0x00020000 /* turn around, MSB. */
+#define MIF_FRAME_TURN_AROUND_LSB 0x00010000 /* turn around, LSB. */
+#define MIF_FRAME_DATA_MASK 0x0000FFFF /* instruction payload */
+
+/* Clause 45 frame field values */
+#define FRAME45_ST 0
+#define FRAME45_OP_ADDR 0
+#define FRAME45_OP_WRITE 1
+#define FRAME45_OP_READ_INC 2
+#define FRAME45_OP_READ 3
+
+typedef union _mif_frame_t {
+
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t st : 2;
+ uint32_t op : 2;
+ uint32_t phyad : 5;
+ uint32_t regad : 5;
+ uint32_t ta_msb : 1;
+ uint32_t ta_lsb : 1;
+ uint32_t data : 16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t data : 16;
+ uint32_t ta_lsb : 1;
+ uint32_t ta_msb : 1;
+ uint32_t regad : 5;
+ uint32_t phyad : 5;
+ uint32_t op : 2;
+ uint32_t st : 2;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mif_frame_t;
+
+#define MIF_CFG_POLL_EN 0x00000008 /* enable polling */
+#define MIF_CFG_BB_MODE 0x00000010 /* bit-bang mode */
+#define MIF_CFG_POLL_REG_MASK 0x000003E0 /* reg addr to be polled */
+#define MIF_CFG_POLL_REG_SHIFT 5
+#define MIF_CFG_POLL_PHY_MASK 0x00007C00 /* XCVR addr to be polled */
+#define MIF_CFG_POLL_PHY_SHIFT 10
+#define MIF_CFG_INDIRECT_MODE 0x0000800
+ /* used to decide if Cl 22 */
+ /* or Cl 45 frame is */
+ /* constructed. */
+ /* 1 = Clause 45,ST = '00' */
+ /* 0 = Clause 22,ST = '01' */
+#define MIF_CFG_ATCE_GE_EN 0x00010000 /* Enable ATCA gigabit mode */
+
+typedef union _mif_cfg_t {
+
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2 : 15;
+ uint32_t atca_ge : 1;
+ uint32_t indirect_md : 1;
+ uint32_t phy_addr : 5;
+ uint32_t reg_addr : 5;
+ uint32_t bb_mode : 1;
+ uint32_t poll_en : 1;
+ uint32_t res1 : 2;
+ uint32_t res : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res : 1;
+ uint32_t res1 : 2;
+ uint32_t poll_en : 1;
+ uint32_t bb_mode : 1;
+ uint32_t reg_addr : 5;
+ uint32_t phy_addr : 5;
+ uint32_t indirect_md : 1;
+ uint32_t atca_ge : 1;
+ uint32_t res2 : 15;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+
+} mif_cfg_t;
+
+#define MIF_POLL_STATUS_DATA_MASK 0xffff0000
+#define MIF_POLL_STATUS_STAT_MASK 0x0000ffff
+
+typedef union _mif_poll_stat_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t data;
+ uint16_t status;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t status;
+ uint16_t data;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mif_poll_stat_t;
+
+
+#define MIF_POLL_MASK_MASK 0x0000ffff
+
+typedef union _mif_poll_mask_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t rsvd;
+ uint16_t mask;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t mask;
+ uint16_t rsvd;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mif_poll_mask_t;
+
+#define MIF_STATUS_INIT_DONE_MASK 0x00000001
+#define MIF_STATUS_XGE_ERR0_MASK 0x00000002
+#define MIF_STATUS_XGE_ERR1_MASK 0x00000004
+#define MIF_STATUS_PEU_ERR_MASK 0x00000008
+#define MIF_STATUS_EXT_PHY_INTR0_MASK 0x00000010
+#define MIF_STATUS_EXT_PHY_INTR1_MASK 0x00000020
+
+typedef union _mif_stat_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:26;
+ uint32_t ext_phy_intr_flag1:1;
+ uint32_t ext_phy_intr_flag0:1;
+ uint32_t peu_err:1;
+ uint32_t xge_err1:1;
+ uint32_t xge_err0:1;
+ uint32_t mif_init_done_stat:1;
+
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mif_init_done_stat:1;
+ uint32_t xge_err0:1;
+ uint32_t xge_err1:1;
+ uint32_t ext_phy_intr_flag0:1;
+ uint32_t ext_phy_intr_flag1:1;
+ uint32_t rsvd:26;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} mif_stat_t;
+
+/* MIF State Machine Register */
+
+#define MIF_SM_EXECUTION_MASK 0x0000003f /* execution state */
+#define MIF_SM_EXECUTION_SHIFT 0
+#define MIF_SM_CONTROL_MASK 0x000001c0 /* control state */
+#define MIF_SM_CONTROL_MASK_SHIFT 6
+#define MIF_SM_MDI 0x00000200
+#define MIF_SM_MDO 0x00000400
+#define MIF_SM_MDO_EN 0x00000800
+#define MIF_SM_MDC 0x00001000
+#define MIF_SM_MDI_0 0x00002000
+#define MIF_SM_MDI_1 0x00004000
+#define MIF_SM_MDI_2 0x00008000
+#define MIF_SM_PORT_ADDR_MASK 0x001f0000
+#define MIF_SM_PORT_ADDR_SHIFT 16
+#define MIF_SM_INT_SIG_MASK 0xffe00000
+#define MIF_SM_INT_SIG_SHIFT 21
+
+
+/*
+ * ******************** PCS registers *********************************
+ */
+
+/* PCS Registers */
+#define PCS_MII_CTRL_1000_SEL 0x0040 /* reads 1. ignored on wr */
+#define PCS_MII_CTRL_COLLISION_TEST 0x0080 /* COL signal */
+#define PCS_MII_CTRL_DUPLEX 0x0100 /* forced 0x0. */
+#define PCS_MII_RESTART_AUTONEG 0x0200 /* self clearing. */
+#define PCS_MII_ISOLATE 0x0400 /* read 0. ignored on wr */
+#define PCS_MII_POWER_DOWN 0x0800 /* read 0. ignored on wr */
+#define PCS_MII_AUTONEG_EN 0x1000 /* autonegotiation */
+#define PCS_MII_10_100_SEL 0x2000 /* read 0. ignored on wr */
+#define PCS_MII_RESET 0x8000 /* reset PCS. */
+
+typedef union _pcs_ctrl_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0 : 16;
+ uint32_t reset : 1;
+ uint32_t res1 : 1;
+ uint32_t sel_10_100 : 1;
+ uint32_t an_enable : 1;
+ uint32_t pwr_down : 1;
+ uint32_t isolate : 1;
+ uint32_t restart_an : 1;
+ uint32_t duplex : 1;
+ uint32_t col_test : 1;
+ uint32_t sel_1000 : 1;
+ uint32_t res2 : 6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2 : 6;
+ uint32_t sel_1000 : 1;
+ uint32_t col_test : 1;
+ uint32_t duplex : 1;
+ uint32_t restart_an : 1;
+ uint32_t isolate : 1;
+ uint32_t pwr_down : 1;
+ uint32_t an_enable : 1;
+ uint32_t sel_10_100 : 1;
+ uint32_t res1 : 1;
+ uint32_t reset : 1;
+ uint32_t res0 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} pcs_ctrl_t;
+
+#define PCS_MII_STATUS_EXTEND_CAP 0x0001 /* reads 0 */
+#define PCS_MII_STATUS_JABBER_DETECT 0x0002 /* reads 0 */
+#define PCS_MII_STATUS_LINK_STATUS 0x0004 /* link status */
+#define PCS_MII_STATUS_AUTONEG_ABLE 0x0008 /* reads 1 */
+#define PCS_MII_STATUS_REMOTE_FAULT 0x0010 /* remote fault detected */
+#define PCS_MII_STATUS_AUTONEG_COMP 0x0020 /* auto-neg completed */
+#define PCS_MII_STATUS_EXTEND_STATUS 0x0100 /* 1000 Base-X PHY */
+
+typedef union _pcs_stat_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0 : 23;
+ uint32_t ext_stat : 1;
+ uint32_t res1 : 2;
+ uint32_t an_complete : 1;
+ uint32_t remote_fault : 1;
+ uint32_t an_able : 1;
+ uint32_t link_stat : 1;
+ uint32_t jabber_detect : 1;
+ uint32_t ext_cap : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ext_cap : 1;
+ uint32_t jabber_detect : 1;
+ uint32_t link_stat : 1;
+ uint32_t an_able : 1;
+ uint32_t remote_fault : 1;
+ uint32_t an_complete : 1;
+ uint32_t res1 : 2;
+ uint32_t ext_stat : 1;
+ uint32_t res0 : 23;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} pcs_stat_t;
+
+#define PCS_MII_ADVERT_FD 0x0020 /* advertise full duplex */
+#define PCS_MII_ADVERT_HD 0x0040 /* advertise half-duplex */
+#define PCS_MII_ADVERT_SYM_PAUSE 0x0080 /* advertise PAUSE sym */
+#define PCS_MII_ADVERT_ASYM_PAUSE 0x0100 /* advertises PAUSE asym */
+#define PCS_MII_ADVERT_RF_MASK 0x3000 /* remote fault */
+#define PCS_MII_ADVERT_RF_SHIFT 12
+#define PCS_MII_ADVERT_ACK 0x4000 /* (ro) */
+#define PCS_MII_ADVERT_NEXT_PAGE 0x8000 /* (ro) forced 0x0 */
+
+#define PCS_MII_LPA_FD PCS_MII_ADVERT_FD
+#define PCS_MII_LPA_HD PCS_MII_ADVERT_HD
+#define PCS_MII_LPA_SYM_PAUSE PCS_MII_ADVERT_SYM_PAUSE
+#define PCS_MII_LPA_ASYM_PAUSE PCS_MII_ADVERT_ASYM_PAUSE
+#define PCS_MII_LPA_RF_MASK PCS_MII_ADVERT_RF_MASK
+#define PCS_MII_LPA_RF_SHIFT PCS_MII_ADVERT_RF_SHIFT
+#define PCS_MII_LPA_ACK PCS_MII_ADVERT_ACK
+#define PCS_MII_LPA_NEXT_PAGE PCS_MII_ADVERT_NEXT_PAGE
+
+typedef union _pcs_anar_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0 : 16;
+ uint32_t next_page : 1;
+ uint32_t ack : 1;
+ uint32_t remote_fault : 2;
+ uint32_t res1 : 3;
+ uint32_t asm_pause : 1;
+ uint32_t pause : 1;
+ uint32_t half_duplex : 1;
+ uint32_t full_duplex : 1;
+ uint32_t res2 : 5;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2 : 5;
+ uint32_t full_duplex : 1;
+ uint32_t half_duplex : 1;
+ uint32_t pause : 1;
+ uint32_t asm_pause : 1;
+ uint32_t res1 : 3;
+ uint32_t remore_fault : 2;
+ uint32_t ack : 1;
+ uint32_t next_page : 1;
+ uint32_t res0 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} pcs_anar_t, *p_pcs_anar_t;
+
+#define PCS_CFG_EN 0x0001 /* enable PCS. */
+#define PCS_CFG_SD_OVERRIDE 0x0002
+#define PCS_CFG_SD_ACTIVE_LOW 0x0004 /* sig detect active low */
+#define PCS_CFG_JITTER_STUDY_MASK 0x0018 /* jitter measurements */
+#define PCS_CFG_JITTER_STUDY_SHIFT 4
+#define PCS_CFG_10MS_TIMER_OVERRIDE 0x0020 /* shortens autoneg timer */
+#define PCS_CFG_MASK 0x0040 /* PCS global mask bit */
+
+typedef union _pcs_cfg_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0 : 25;
+ uint32_t mask : 1;
+ uint32_t override_10ms_timer : 1;
+ uint32_t jitter_study : 2;
+ uint32_t sig_det_a_low : 1;
+ uint32_t sig_det_override : 1;
+ uint32_t enable : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t enable : 1;
+ uint32_t sig_det_override : 1;
+ uint32_t sig_det_a_low : 1;
+ uint32_t jitter_study : 2;
+ uint32_t override_10ms_timer : 1;
+ uint32_t mask : 1;
+ uint32_t res0 : 25;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} pcs_cfg_t, *p_pcs_cfg_t;
+
+
+/* used for diagnostic purposes. bits 20-22 autoclear on read */
+#define PCS_SM_TX_STATE_MASK 0x0000000F /* Tx idle state mask */
+#define PCS_SM_TX_STATE_SHIFT 0
+#define PCS_SM_RX_STATE_MASK 0x000000F0 /* Rx idle state mask */
+#define PCS_SM_RX_STATE_SHIFT 4
+#define PCS_SM_WORD_SYNC_STATE_MASK 0x00000700 /* loss of sync state mask */
+#define PCS_SM_WORD_SYNC_STATE_SHIFT 8
+#define PCS_SM_SEQ_DETECT_STATE_MASK 0x00001800 /* sequence detect */
+#define PCS_SM_SEQ_DETECT_STATE_SHIFT 11
+#define PCS_SM_LINK_STATE_MASK 0x0001E000 /* link state */
+#define PCS_SM_LINK_STATE_SHIFT 13
+#define PCS_SM_LOSS_LINK_C 0x00100000 /* loss of link */
+#define PCS_SM_LOSS_LINK_SYNC 0x00200000 /* loss of sync */
+#define PCS_SM_LOSS_SIGNAL_DETECT 0x00400000 /* signal detect fail */
+#define PCS_SM_NO_LINK_BREAKLINK 0x01000000 /* receipt of breaklink */
+#define PCS_SM_NO_LINK_SERDES 0x02000000 /* serdes initializing */
+#define PCS_SM_NO_LINK_C 0x04000000 /* C codes not stable */
+#define PCS_SM_NO_LINK_SYNC 0x08000000 /* word sync not achieved */
+#define PCS_SM_NO_LINK_WAIT_C 0x10000000 /* waiting for C codes */
+#define PCS_SM_NO_LINK_NO_IDLE 0x20000000 /* linkpartner send C code */
+
+typedef union _pcs_stat_mc_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2 : 2;
+ uint32_t lnk_dwn_ni : 1;
+ uint32_t lnk_dwn_wc : 1;
+ uint32_t lnk_dwn_ls : 1;
+ uint32_t lnk_dwn_nc : 1;
+ uint32_t lnk_dwn_ser : 1;
+ uint32_t lnk_loss_bc : 1;
+ uint32_t res1 : 1;
+ uint32_t loss_sd : 1;
+ uint32_t lnk_loss_sync : 1;
+ uint32_t lnk_loss_c : 1;
+ uint32_t res0 : 3;
+ uint32_t link_cfg_stat : 4;
+ uint32_t seq_detc_stat : 2;
+ uint32_t word_sync : 3;
+ uint32_t rx_ctrl : 4;
+ uint32_t tx_ctrl : 4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t tx_ctrl : 4;
+ uint32_t rx_ctrl : 4;
+ uint32_t word_sync : 3;
+ uint32_t seq_detc_stat : 2;
+ uint32_t link_cfg_stat : 4;
+ uint32_t res0 : 3;
+ uint32_t lnk_loss_c : 1;
+ uint32_t lnk_loss_sync : 1;
+ uint32_t loss_sd : 1;
+ uint32_t res1 : 1;
+ uint32_t lnk_loss_bc : 1;
+ uint32_t lnk_dwn_ser : 1;
+ uint32_t lnk_dwn_nc : 1;
+ uint32_t lnk_dwn_ls : 1;
+ uint32_t lnk_dwn_wc : 1;
+ uint32_t lnk_dwn_ni : 1;
+ uint32_t res2 : 2;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} pcs_stat_mc_t, *p_pcs_stat_mc_t;
+
+#define PCS_INTR_STATUS_LINK_CHANGE 0x04 /* link status has changed */
+
+/*
+ * control which network interface is used. no more than one bit should
+ * be set.
+ */
+#define PCS_DATAPATH_MODE_PCS 0 /* Internal PCS is used */
+#define PCS_DATAPATH_MODE_MII 0x00000002 /* GMII/RGMII is selected. */
+
+#define PCS_PACKET_COUNT_TX_MASK 0x000007FF /* pkts xmitted by PCS */
+#define PCS_PACKET_COUNT_RX_MASK 0x07FF0000 /* pkts recvd by PCS */
+#define PCS_PACKET_COUNT_RX_SHIFT 16
+
+/*
+ * ******************** XPCS registers *********************************
+ */
+
+/* XPCS Base 10G Control1 Register */
+#define XPCS_CTRL1_RST 0x8000 /* Self clearing reset. */
+#define XPCS_CTRL1_LOOPBK 0x4000 /* xpcs Loopback */
+#define XPCS_CTRL1_SPEED_SEL_3 0x2000 /* 1 indicates 10G speed */
+#define XPCS_CTRL1_LOW_PWR 0x0800 /* low power mode. */
+#define XPCS_CTRL1_SPEED_SEL_1 0x0040 /* 1 indicates 10G speed */
+#define XPCS_CTRL1_SPEED_SEL_0_MASK 0x003c /* 0 indicates 10G speed. */
+#define XPCS_CTRL1_SPEED_SEL_0_SHIFT 2
+
+
+
+typedef union _xpcs_ctrl1_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res3 : 16;
+ uint32_t reset : 1;
+ uint32_t csr_lb : 1;
+ uint32_t csr_speed_sel3 : 1;
+ uint32_t res2 : 1;
+ uint32_t csr_low_pwr : 1;
+ uint32_t res1 : 4;
+ uint32_t csr_speed_sel1 : 1;
+ uint32_t csr_speed_sel0 : 4;
+ uint32_t res0 : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res0 : 2;
+ uint32_t csr_speed_sel0 : 4;
+ uint32_t csr_speed_sel1 : 1;
+ uint32_t res1 : 4;
+ uint32_t csr_low_pwr : 1;
+ uint32_t res2 : 1;
+ uint32_t csr_speed_sel3 : 1;
+ uint32_t csr_lb : 1;
+ uint32_t reset : 1;
+ uint32_t res3 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_ctrl1_t;
+
+
+/* XPCS Base 10G Status1 Register (Read Only) */
+#define XPCS_STATUS1_FAULT 0x0080
+#define XPCS_STATUS1_RX_LINK_STATUS_UP 0x0004 /* Link status interrupt */
+#define XPCS_STATUS1_LOW_POWER_ABILITY 0x0002 /* low power mode */
+
+
+typedef union _xpcs_stat1_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res4 : 16;
+ uint32_t res3 : 8;
+ uint32_t csr_fault : 1;
+ uint32_t res1 : 4;
+ uint32_t csr_rx_link_stat : 1;
+ uint32_t csr_low_pwr_ability : 1;
+ uint32_t res0 : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res0 : 1;
+ uint32_t csr_low_pwr_ability : 1;
+ uint32_t csr_rx_link_stat : 1;
+ uint32_t res1 : 4;
+ uint32_t csr_fault : 1;
+ uint32_t res3 : 8;
+ uint32_t res4 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_stat1_t;
+
+
+/* XPCS Base Speed Ability Register. Indicates 10G capability */
+#define XPCS_SPEED_ABILITY_10_GIG 0x0001
+
+
+typedef union _xpcs_speed_ab_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1 : 16;
+ uint32_t res0 : 15;
+ uint32_t csr_10gig : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t csr_10gig : 1;
+ uint32_t res0 : 15;
+ uint32_t res1 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_speed_ab_t;
+
+
+/* XPCS Base 10G Devices in Package Register */
+#define XPCS_DEV_IN_PKG_CSR_VENDOR2 0x80000000
+#define XPCS_DEV_IN_PKG_CSR_VENDOR1 0x40000000
+#define XPCS_DEV_IN_PKG_DTE_XS 0x00000020
+#define XPCS_DEV_IN_PKG_PHY_XS 0x00000010
+#define XPCS_DEV_IN_PKG_PCS 0x00000008
+#define XPCS_DEV_IN_PKG_WIS 0x00000004
+#define XPCS_DEV_IN_PKG_PMD_PMA 0x00000002
+#define XPCS_DEV_IN_PKG_CLS_22_REG 0x00000000
+
+
+
+typedef union _xpcs_dev_in_pkg_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t csr_vendor2 : 1;
+ uint32_t csr_vendor1 : 1;
+ uint32_t res1 : 14;
+ uint32_t res0 : 10;
+ uint32_t dte_xs : 1;
+ uint32_t phy_xs : 1;
+ uint32_t pcs : 1;
+ uint32_t wis : 1;
+ uint32_t pmd_pma : 1;
+ uint32_t clause_22_reg : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t clause_22_reg : 1;
+ uint32_t pmd_pma : 1;
+ uint32_t wis : 1;
+ uint32_t pcs : 1;
+ uint32_t phy_xs : 1;
+ uint32_t dte_xs : 1;
+ uint32_t res0 : 10;
+ uint32_t res1 : 14;
+ uint32_t csr_vendor1 : 1;
+ uint32_t csr_vendor2 : 1;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_dev_in_pkg_t;
+
+
+/* XPCS Base 10G Control2 Register */
+#define XPCS_PSC_SEL_MASK 0x0003
+#define PSC_SEL_10G_BASE_X_PCS 0x0001
+
+
+typedef union _xpcs_ctrl2_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1 : 16;
+ uint32_t res0 : 14;
+ uint32_t csr_psc_sel : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t csr_psc_sel : 2;
+ uint32_t res0 : 14;
+ uint32_t res1 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_ctrl2_t;
+
+
+/* XPCS Base10G Status2 Register */
+#define XPCS_STATUS2_DEV_PRESENT_MASK 0xc000 /* ?????? */
+#define XPCS_STATUS2_TX_FAULT 0x0800 /* Fault on tx path */
+#define XPCS_STATUS2_RX_FAULT 0x0400 /* Fault on rx path */
+#define XPCS_STATUS2_TEN_GBASE_W 0x0004 /* 10G-Base-W */
+#define XPCS_STATUS2_TEN_GBASE_X 0x0002 /* 10G-Base-X */
+#define XPCS_STATUS2_TEN_GBASE_R 0x0001 /* 10G-Base-R */
+
+typedef union _xpcs_stat2_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2 : 16;
+ uint32_t csr_dev_pres : 2;
+ uint32_t res1 : 2;
+ uint32_t csr_tx_fault : 1;
+ uint32_t csr_rx_fault : 1;
+ uint32_t res0 : 7;
+ uint32_t ten_gbase_w : 1;
+ uint32_t ten_gbase_x : 1;
+ uint32_t ten_gbase_r : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ten_gbase_r : 1;
+ uint32_t ten_gbase_x : 1;
+ uint32_t ten_gbase_w : 1;
+ uint32_t res0 : 7;
+ uint32_t csr_rx_fault : 1;
+ uint32_t csr_tx_fault : 1;
+ uint32_t res1 : 2;
+ uint32_t csr_dev_pres : 2;
+ uint32_t res2 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_stat2_t;
+
+
+
+/* XPCS Base10G Status Register */
+#define XPCS_STATUS_LANE_ALIGN 0x1000 /* 10GBaseX PCS rx lanes align */
+#define XPCS_STATUS_PATTERN_TEST_ABLE 0x0800 /* able to generate patterns. */
+#define XPCS_STATUS_LANE3_SYNC 0x0008 /* Lane 3 is synchronized */
+#define XPCS_STATUS_LANE2_SYNC 0x0004 /* Lane 2 is synchronized */
+#define XPCS_STATUS_LANE1_SYNC 0x0002 /* Lane 1 is synchronized */
+#define XPCS_STATUS_LANE0_SYNC 0x0001 /* Lane 0 is synchronized */
+
+typedef union _xpcs_stat_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2 : 16;
+ uint32_t res1 : 3;
+ uint32_t csr_lane_align : 1;
+ uint32_t csr_pattern_test_able : 1;
+ uint32_t res0 : 7;
+ uint32_t csr_lane3_sync : 1;
+ uint32_t csr_lane2_sync : 1;
+ uint32_t csr_lane1_sync : 1;
+ uint32_t csr_lane0_sync : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t csr_lane0_sync : 1;
+ uint32_t csr_lane1_sync : 1;
+ uint32_t csr_lane2_sync : 1;
+ uint32_t csr_lane3_sync : 1;
+ uint32_t res0 : 7;
+ uint32_t csr_pat_test_able : 1;
+ uint32_t csr_lane_align : 1;
+ uint32_t res1 : 3;
+ uint32_t res2 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_stat_t;
+
+/* XPCS Base10G Test Control Register */
+#define XPCS_TEST_CTRL_TX_TEST_ENABLE 0x0004
+#define XPCS_TEST_CTRL_TEST_PATTERN_SEL_MASK 0x0003
+#define TEST_PATTERN_HIGH_FREQ 0
+#define TEST_PATTERN_LOW_FREQ 1
+#define TEST_PATTERN_MIXED_FREQ 2
+
+typedef union _xpcs_test_ctl_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1 : 16;
+ uint32_t res0 : 13;
+ uint32_t csr_tx_test_en : 1;
+ uint32_t csr_test_pat_sel : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t csr_test_pat_sel : 2;
+ uint32_t csr_tx_test_en : 1;
+ uint32_t res0 : 13;
+ uint32_t res1 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_test_ctl_t;
+
+/* XPCS Base10G Diagnostic Register */
+#define XPCS_DIAG_EB_ALIGN_ERR3 0x40
+#define XPCS_DIAG_EB_ALIGN_ERR2 0x20
+#define XPCS_DIAG_EB_ALIGN_ERR1 0x10
+#define XPCS_DIAG_EB_DESKEW_OK 0x08
+#define XPCS_DIAG_EB_ALIGN_DET3 0x04
+#define XPCS_DIAG_EB_ALIGN_DET2 0x02
+#define XPCS_DIAG_EB_ALIGN_DET1 0x01
+#define XPCS_DIAG_EB_DESKEW_LOSS 0
+
+#define XPCS_DIAG_SYNC_3_INVALID 0x8
+#define XPCS_DIAG_SYNC_2_INVALID 0x4
+#define XPCS_DIAG_SYNC_1_INVALID 0x2
+#define XPCS_DIAG_SYNC_IN_SYNC 0x1
+#define XPCS_DIAG_SYNC_LOSS_SYNC 0
+
+#define XPCS_RX_SM_RECEIVE_STATE 1
+#define XPCS_RX_SM_FAULT_STATE 0
+
+typedef union _xpcs_diag_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1 : 7;
+ uint32_t sync_sm_lane3 : 4;
+ uint32_t sync_sm_lane2 : 4;
+ uint32_t sync_sm_lane1 : 4;
+ uint32_t sync_sm_lane0 : 4;
+ uint32_t elastic_buffer_sm : 8;
+ uint32_t receive_sm : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t receive_sm : 1;
+ uint32_t elastic_buffer_sm : 8;
+ uint32_t sync_sm_lane0 : 4;
+ uint32_t sync_sm_lane1 : 4;
+ uint32_t sync_sm_lane2 : 4;
+ uint32_t sync_sm_lane3 : 4;
+ uint32_t res1 : 7;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_diag_t;
+
+/* XPCS Base10G Tx State Machine Register */
+#define XPCS_TX_SM_SEND_UNDERRUN 0x9
+#define XPCS_TX_SM_SEND_RANDOM_Q 0x8
+#define XPCS_TX_SM_SEND_RANDOM_K 0x7
+#define XPCS_TX_SM_SEND_RANDOM_A 0x6
+#define XPCS_TX_SM_SEND_RANDOM_R 0x5
+#define XPCS_TX_SM_SEND_Q 0x4
+#define XPCS_TX_SM_SEND_K 0x3
+#define XPCS_TX_SM_SEND_A 0x2
+#define XPCS_TX_SM_SEND_SDP 0x1
+#define XPCS_TX_SM_SEND_DATA 0
+
+/* XPCS Base10G Configuration Register */
+#define XPCS_CFG_VENDOR_DBG_SEL_MASK 0x78
+#define XPCS_CFG_VENDOR_DBG_SEL_SHIFT 3
+#define XPCS_CFG_BYPASS_SIG_DETECT 0x0004
+#define XPCS_CFG_ENABLE_TX_BUFFERS 0x0002
+#define XPCS_CFG_XPCS_ENABLE 0x0001
+
+typedef union _xpcs_config_t {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t msw; /* Most significant word */
+ uint32_t lsw; /* Least significant word */
+#elif defined(_LITTLE_ENDIAN)
+ uint32_t lsw; /* Least significant word */
+ uint32_t msw; /* Most significant word */
+#endif
+ } val;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1 : 16;
+ uint32_t res0 : 9;
+ uint32_t csr_vendor_dbg_sel : 4;
+ uint32_t csr_bypass_sig_detect : 1;
+ uint32_t csr_en_tx_buf : 1;
+ uint32_t csr_xpcs_en : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t csr_xpcs_en : 1;
+ uint32_t csr_en_tx_buf : 1;
+ uint32_t csr_bypass_sig_detect : 1;
+ uint32_t csr_vendor_dbg_sel : 4;
+ uint32_t res0 : 9;
+ uint32_t res1 : 16;
+#endif
+ } w0;
+
+#if defined(_LITTLE_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} xpcs_config_t;
+
+
+
+/* XPCS Base10G Mask1 Register */
+#define XPCS_MASK1_FAULT_MASK 0x0080 /* mask fault interrupt. */
+#define XPCS_MASK1_RX_LINK_STATUS_MASK 0x0040 /* mask linkstat interrupt */
+
+/* XPCS Base10G Packet Counter */
+#define XPCS_PKT_CNTR_TX_PKT_CNT_MASK 0xffff0000
+#define XPCS_PKT_CNTR_TX_PKT_CNT_SHIFT 16
+#define XPCS_PKT_CNTR_RX_PKT_CNT_MASK 0x0000ffff
+#define XPCS_PKT_CNTR_RX_PKT_CNT_SHIFT 0
+
+/* XPCS Base10G TX State Machine status register */
+#define XPCS_TX_STATE_MC_TX_STATE_MASK 0x0f
+#define XPCS_DESKEW_ERR_CNTR_MASK 0xff
+
+/* XPCS Base10G Lane symbol error counters */
+#define XPCS_SYM_ERR_CNT_L1_MASK 0xffff0000
+#define XPCS_SYM_ERR_CNT_L0_MASK 0x0000ffff
+#define XPCS_SYM_ERR_CNT_L3_MASK 0xffff0000
+#define XPCS_SYM_ERR_CNT_L2_MASK 0x0000ffff
+
+#define XPCS_SYM_ERR_CNT_MULTIPLIER 16
+
+/* ESR Reset Register */
+#define ESR_RESET_1 2
+#define ESR_RESET_0 1
+
+/* ESR Configuration Register */
+#define ESR_BLUNT_END_LOOPBACK 2
+#define ESR_FORCE_SERDES_SERDES_RDY 1
+
+/* ESR Neptune Serdes PLL Configuration */
+#define ESR_PLL_CFG_FBDIV_0 0x1
+#define ESR_PLL_CFG_FBDIV_1 0x2
+#define ESR_PLL_CFG_FBDIV_2 0x4
+#define ESR_PLL_CFG_HALF_RATE_0 0x8
+#define ESR_PLL_CFG_HALF_RATE_1 0x10
+#define ESR_PLL_CFG_HALF_RATE_2 0x20
+#define ESR_PLL_CFG_HALF_RATE_3 0x40
+
+/* ESR Neptune Serdes Control Register */
+#define ESR_CTL_EN_SYNCDET_0 0x00000001
+#define ESR_CTL_EN_SYNCDET_1 0x00000002
+#define ESR_CTL_EN_SYNCDET_2 0x00000004
+#define ESR_CTL_EN_SYNCDET_3 0x00000008
+#define ESR_CTL_OUT_EMPH_0_MASK 0x00000070
+#define ESR_CTL_OUT_EMPH_0_SHIFT 4
+#define ESR_CTL_OUT_EMPH_1_MASK 0x00000380
+#define ESR_CTL_OUT_EMPH_1_SHIFT 7
+#define ESR_CTL_OUT_EMPH_2_MASK 0x00001c00
+#define ESR_CTL_OUT_EMPH_2_SHIFT 10
+#define ESR_CTL_OUT_EMPH_3_MASK 0x0000e000
+#define ESR_CTL_OUT_EMPH_3_SHIFT 13
+#define ESR_CTL_LOSADJ_0_MASK 0x00070000
+#define ESR_CTL_LOSADJ_0_SHIFT 16
+#define ESR_CTL_LOSADJ_1_MASK 0x00380000
+#define ESR_CTL_LOSADJ_1_SHIFT 19
+#define ESR_CTL_LOSADJ_2_MASK 0x01c00000
+#define ESR_CTL_LOSADJ_2_SHIFT 22
+#define ESR_CTL_LOSADJ_3_MASK 0x0e000000
+#define ESR_CTL_LOSADJ_3_SHIFT 25
+#define ESR_CTL_RXITERM_0 0x10000000
+#define ESR_CTL_RXITERM_1 0x20000000
+#define ESR_CTL_RXITERM_2 0x40000000
+#define ESR_CTL_RXITERM_3 0x80000000
+
+/* ESR Neptune Serdes Test Configuration Register */
+#define ESR_TSTCFG_LBTEST_MD_0_MASK 0x00000003
+#define ESR_TSTCFG_LBTEST_MD_0_SHIFT 0
+#define ESR_TSTCFG_LBTEST_MD_1_MASK 0x0000000c
+#define ESR_TSTCFG_LBTEST_MD_1_SHIFT 2
+#define ESR_TSTCFG_LBTEST_MD_2_MASK 0x00000030
+#define ESR_TSTCFG_LBTEST_MD_2_SHIFT 4
+#define ESR_TSTCFG_LBTEST_MD_3_MASK 0x000000c0
+#define ESR_TSTCFG_LBTEST_MD_3_SHIFT 6
+
+/* ESR Neptune Ethernet RGMII Configuration Register */
+#define ESR_RGMII_PT0_IN_USE 0x00000001
+#define ESR_RGMII_PT1_IN_USE 0x00000002
+#define ESR_RGMII_PT2_IN_USE 0x00000004
+#define ESR_RGMII_PT3_IN_USE 0x00000008
+#define ESR_RGMII_REG_RW_TEST 0x00000010
+
+/* ESR Internal Signals Observation Register */
+#define ESR_SIG_MASK 0xFFFFFFFF
+#define ESR_SIG_P0_BITS_MASK 0x33E0000F
+#define ESR_SIG_P1_BITS_MASK 0x0C1F00F0
+#define ESR_SIG_SERDES_RDY0_P0 0x20000000
+#define ESR_SIG_DETECT0_P0 0x10000000
+#define ESR_SIG_SERDES_RDY0_P1 0x08000000
+#define ESR_SIG_DETECT0_P1 0x04000000
+#define ESR_SIG_XSERDES_RDY_P0 0x02000000
+#define ESR_SIG_XDETECT_P0_CH3 0x01000000
+#define ESR_SIG_XDETECT_P0_CH2 0x00800000
+#define ESR_SIG_XDETECT_P0_CH1 0x00400000
+#define ESR_SIG_XDETECT_P0_CH0 0x00200000
+#define ESR_SIG_XSERDES_RDY_P1 0x00100000
+#define ESR_SIG_XDETECT_P1_CH3 0x00080000
+#define ESR_SIG_XDETECT_P1_CH2 0x00040000
+#define ESR_SIG_XDETECT_P1_CH1 0x00020000
+#define ESR_SIG_XDETECT_P1_CH0 0x00010000
+#define ESR_SIG_LOS_P1_CH3 0x00000080
+#define ESR_SIG_LOS_P1_CH2 0x00000040
+#define ESR_SIG_LOS_P1_CH1 0x00000020
+#define ESR_SIG_LOS_P1_CH0 0x00000010
+#define ESR_SIG_LOS_P0_CH3 0x00000008
+#define ESR_SIG_LOS_P0_CH2 0x00000004
+#define ESR_SIG_LOS_P0_CH1 0x00000002
+#define ESR_SIG_LOS_P0_CH0 0x00000001
+
+/* ESR Debug Selection Register */
+#define ESR_DEBUG_SEL_MASK 0x00000003f
+
+/* ESR Test Configuration Register */
+#define ESR_NO_LOOPBACK_CH3 (0x0 << 6)
+#define ESR_EWRAP_CH3 (0x1 << 6)
+#define ESR_PAD_LOOPBACK_CH3 (0x2 << 6)
+#define ESR_REVLOOPBACK_CH3 (0x3 << 6)
+#define ESR_NO_LOOPBACK_CH2 (0x0 << 4)
+#define ESR_EWRAP_CH2 (0x1 << 4)
+#define ESR_PAD_LOOPBACK_CH2 (0x2 << 4)
+#define ESR_REVLOOPBACK_CH2 (0x3 << 4)
+#define ESR_NO_LOOPBACK_CH1 (0x0 << 2)
+#define ESR_EWRAP_CH1 (0x1 << 2)
+#define ESR_PAD_LOOPBACK_CH1 (0x2 << 2)
+#define ESR_REVLOOPBACK_CH1 (0x3 << 2)
+#define ESR_NO_LOOPBACK_CH0 0x0
+#define ESR_EWRAP_CH0 0x1
+#define ESR_PAD_LOOPBACK_CH0 0x2
+#define ESR_REVLOOPBACK_CH0 0x3
+
+/* convert values */
+#define NXGE_BASE(x, y) \
+ (((y) << (x ## _SHIFT)) & (x ## _MASK))
+
+#define NXGE_VAL_GET(fieldname, regval) \
+ (((regval) & ((fieldname) ## _MASK)) >> ((fieldname) ## _SHIFT))
+
+#define NXGE_VAL_SET(fieldname, regval, val) \
+{ \
+ (regval) &= ~((fieldname) ## _MASK); \
+ (regval) |= ((val) << (fieldname ## _SHIFT)); \
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_MAC_NXGE_MAC_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_mii.h b/usr/src/uts/sun4v/sys/nxge/nxge_mii.h
new file mode 100644
index 0000000000..9c801b794c
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_mii.h
@@ -0,0 +1,454 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_MII_H_
+#define _SYS_NXGE_NXGE_MII_H_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Configuration Register space.
+ */
+
+#define MII_BMCR 0
+#define MII_BMSR 1
+#define MII_IDR1 2
+#define MII_IDR2 3
+#define MII_ANAR 4
+#define MII_ANLPAR 5
+#define MII_ANER 6
+#define MII_NPTXR 7
+#define MII_LPRXNPR 8
+#define MII_GCR 9
+#define MII_GSR 10
+#define MII_RES0 11
+#define MII_RES1 12
+#define MII_RES2 13
+#define MII_RES3 14
+#define MII_ESR 15
+
+#define NXGE_MAX_MII_REGS 32
+
+/*
+ * Configuration Register space.
+ */
+typedef struct _mii_regs {
+ uchar_t bmcr; /* Basic mode control register */
+ uchar_t bmsr; /* Basic mode status register */
+ uchar_t idr1; /* Phy identifier register 1 */
+ uchar_t idr2; /* Phy identifier register 2 */
+ uchar_t anar; /* Auto-Negotiation advertisement register */
+ uchar_t anlpar; /* Auto-Negotiation link Partner ability reg */
+ uchar_t aner; /* Auto-Negotiation expansion register */
+ uchar_t nptxr; /* Next page transmit register */
+ uchar_t lprxnpr; /* Link partner received next page register */
+ uchar_t gcr; /* Gigabit basic mode control register. */
+ uchar_t gsr; /* Gigabit basic mode status register */
+ uchar_t mii_res1[4]; /* For future use by MII working group */
+ uchar_t esr; /* Extended status register. */
+ uchar_t vendor_res[16]; /* For future use by Phy Vendors */
+} mii_regs_t, *p_mii_regs_t;
+
+/*
+ * MII Register 0: Basic mode control register.
+ */
+#define BMCR_RES 0x003f /* Unused... */
+#define BMCR_SSEL_MSB 0x0040 /* Used to manually select speed */
+ /* (with * bit 6) when auto-neg */
+ /* disabled */
+#define BMCR_COL_TEST 0x0080 /* Collision test */
+#define BMCR_DPLX_MD 0x0100 /* Full duplex */
+#define BMCR_RESTART_AN 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect BCM5464R from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the BCM5464R */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SSEL_LSB 0x2000 /* Used to manually select speed */
+ /* (with bit 13) when auto-neg */
+ /* disabled */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the BCM5464R */
+
+typedef union _mii_bmcr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t reset:1;
+ uint16_t loopback:1;
+ uint16_t speed_sel:1;
+ uint16_t enable_autoneg:1;
+ uint16_t power_down:1;
+ uint16_t isolate:1;
+ uint16_t restart_autoneg:1;
+ uint16_t duplex_mode:1;
+ uint16_t col_test:1;
+ uint16_t speed_1000_sel:1;
+ uint16_t res1:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res1:6;
+ uint16_t speed_1000_sel:1;
+ uint16_t col_test:1;
+ uint16_t duplex_mode:1;
+ uint16_t restart_autoneg:1;
+ uint16_t isolate:1;
+ uint16_t power_down:1;
+ uint16_t enable_autoneg:1;
+ uint16_t speed_sel:1;
+ uint16_t loopback:1;
+ uint16_t reset:1;
+#endif
+ } bits;
+} mii_bmcr_t, *p_mii_bmcr_t;
+
+/*
+ * MII Register 1: Basic mode status register.
+ */
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_MF_PRE_SUP 0x0040 /* Preamble for MIF frame suppressed, */
+ /* always 1 for BCM5464R */
+#define BMSR_RESV 0x0080 /* Unused... */
+#define BMSR_ESTAT 0x0100 /* Contains IEEE extended status reg */
+#define BMSR_100BASE2HALF 0x0200 /* Can do 100mbps, 2k pkts half-dplx */
+#define BMSR_100BASE2FULL 0x0400 /* Can do 100mbps, 2k pkts full-dplx */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+typedef union _mii_bmsr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t link_100T4:1;
+ uint16_t link_100fdx:1;
+ uint16_t link_100hdx:1;
+ uint16_t link_10fdx:1;
+ uint16_t link_10hdx:1;
+ uint16_t res2:2;
+ uint16_t extend_status:1;
+ uint16_t res1:1;
+ uint16_t preamble_supress:1;
+ uint16_t auto_neg_complete:1;
+ uint16_t remote_fault:1;
+ uint16_t auto_neg_able:1;
+ uint16_t link_status:1;
+ uint16_t jabber_detect:1;
+ uint16_t ext_cap:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ int16_t ext_cap:1;
+ uint16_t jabber_detect:1;
+ uint16_t link_status:1;
+ uint16_t auto_neg_able:1;
+ uint16_t remote_fault:1;
+ uint16_t auto_neg_complete:1;
+ uint16_t preamble_supress:1;
+ uint16_t res1:1;
+ uint16_t extend_status:1;
+ uint16_t res2:2;
+ uint16_t link_10hdx:1;
+ uint16_t link_10fdx:1;
+ uint16_t link_100hdx:1;
+ uint16_t link_100fdx:1;
+ uint16_t link_100T4:1;
+#endif
+ } bits;
+} mii_bmsr_t, *p_mii_bmsr_t;
+
+/*
+ * MII Register 2: Physical Identifier 1.
+ */
+/* contains BCM OUI bits [3:18] */
+typedef union _mii_idr1 {
+ uint16_t value;
+ struct {
+ uint16_t ieee_address:16;
+ } bits;
+} mii_idr1_t, *p_mii_idr1_t;
+
+/*
+ * MII Register 3: Physical Identifier 2.
+ */
+typedef union _mii_idr2 {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t ieee_address:6;
+ uint16_t model_no:6;
+ uint16_t rev_no:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t rev_no:4;
+ uint16_t model_no:6;
+ uint16_t ieee_address:6;
+#endif
+ } bits;
+} mii_idr2_t, *p_mii_idr2_t;
+
+/*
+ * MII Register 4: Auto-negotiation advertisement register.
+ */
+#define ADVERTISE_SLCT 0x001f /* Selector bits for proto, 0x01 */
+ /* indicates IEEE 802.3 CSMA/CD phy */
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets. set to */
+ /* 0, BCM5464R not 100BASE-T4 capable */
+#define ADVERTISE_RES1 0x0400 /* Unused... */
+#define ADVERTISE_ASM_PAUS 0x0800 /* advertise asymmetric pause */
+#define ADVERTISE_PAUS 0x1000 /* can do full dplx pause */
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
+#define ADVERTISE_RES0 0x4000 /* Unused... */
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+typedef union _mii_anar {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t np_indication:1;
+ uint16_t acknowledge:1;
+ uint16_t remote_fault:1;
+ uint16_t res1:1;
+ uint16_t cap_asmpause:1;
+ uint16_t cap_pause:1;
+ uint16_t cap_100T4:1;
+ uint16_t cap_100fdx:1;
+ uint16_t cap_100hdx:1;
+ uint16_t cap_10fdx:1;
+ uint16_t cap_10hdx:1;
+ uint16_t selector:5;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t selector:5;
+ uint16_t cap_10hdx:1;
+ uint16_t cap_10fdx:1;
+ uint16_t cap_100hdx:1;
+ uint16_t cap_100fdx:1;
+ uint16_t cap_100T4:1;
+ uint16_t cap_pause:1;
+ uint16_t cap_asmpause:1;
+ uint16_t res1:1;
+ uint16_t remote_fault:1;
+ uint16_t acknowledge:1;
+ uint16_t np_indication:1;
+#endif
+ } bits;
+} mii_anar_t, *p_mii_anar_t;
+
+/*
+ * MII Register 5: Auto-negotiation link partner ability register.
+ */
+#define LPA_SLCT 0x001f /* Same as advertise selector */
+#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
+#define LPA_RES1 0x0400 /* Unused... */
+#define LPA_ASM_PAUS 0x0800 /* advertise asymmetric pause */
+#define LPA__PAUS 0x1000 /* can do full dplx pause */
+#define LPA_RFAULT 0x2000 /* Link partner faulted */
+#define LPA_LPACK 0x4000 /* Link partner acked us */
+#define LPA_NPAGE 0x8000 /* Next page bit */
+
+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+typedef mii_anar_t mii_anlpar_t, *pmii_anlpar_t;
+
+/*
+ * MII Register 6: Auto-negotiation expansion register.
+ */
+#define EXPANSION_LP_AN_ABLE 0x0001 /* Link partner has auto-neg cap */
+#define EXPANSION_PG_RX 0x0002 /* Got new RX page code word */
+#define EXPANSION_NP_ABLE 0x0004 /* This enables npage words */
+#define EXPANSION_LPNP_ABLE 0x0008 /* Link partner supports npage */
+#define EXPANSION_MFAULTS 0x0010 /* Multiple link faults detected */
+#define EXPANSION_RESV 0xffe0 /* Unused... */
+
+typedef union _mii_aner {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res:11;
+ uint16_t mlf:1;
+ uint16_t lp_np_able:1;
+ uint16_t np_able:1;
+ uint16_t page_rx:1;
+ uint16_t lp_an_able:1;
+#else
+ uint16_t lp_an_able:1;
+ uint16_t page_rx:1;
+ uint16_t np_able:1;
+ uint16_t lp_np_able:1;
+ uint16_t mlf:1;
+ uint16_t res:11;
+#endif
+ } bits;
+} mii_aner_t, *p_mii_aner_t;
+
+/*
+ * MII Register 7: Next page transmit register.
+ */
+typedef union _mii_nptxr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t np:1;
+ uint16_t res:1;
+ uint16_t msgp:1;
+ uint16_t ack2:1;
+ uint16_t toggle:1;
+ uint16_t res1:11;
+#else
+ uint16_t res1:11;
+ uint16_t toggle:1;
+ uint16_t ack2:1;
+ uint16_t msgp:1;
+ uint16_t res:1;
+ uint16_t np:1;
+#endif
+ } bits;
+} mii_nptxr_t, *p_mii_nptxr_t;
+
+/*
+ * MII Register 8: Link partner received next page register.
+ */
+typedef union _mii_lprxnpr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t np:1;
+ uint16_t ack:1;
+ uint16_t msgp:1;
+ uint16_t ack2:1;
+ uint16_t toggle:1;
+ uint16_t mcf:11;
+#else
+ uint16_t mcf:11;
+ uint16_t toggle:1;
+ uint16_t ack2:1;
+ uint16_t msgp:1;
+ uint16_t ack:1;
+ uint16_t np:1;
+#endif
+ } bits;
+} mii_lprxnpr_t, *p_mii_lprxnpr_t;
+
+/*
+ * MII Register 9: 1000BaseT control register.
+ */
+typedef union _mii_gcr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t test_mode:3;
+ uint16_t ms_mode_en:1;
+ uint16_t master:1;
+ uint16_t dte_or_repeater:1;
+ uint16_t link_1000fdx:1;
+ uint16_t link_1000hdx:1;
+ uint16_t res:8;
+#else
+ uint16_t res:8;
+ uint16_t link_1000hdx:1;
+ uint16_t link_1000fdx:1;
+ uint16_t dte_or_repeater:1;
+ uint16_t master:1;
+ uint16_t ms_mode_en:1;
+ uint16_t test_mode:3;
+#endif
+ } bits;
+} mii_gcr_t, *p_mii_gcr_t;
+
+/*
+ * MII Register 10: 1000BaseT status register.
+ */
+typedef union _mii_gsr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t ms_config_fault:1;
+ uint16_t ms_resolve:1;
+ uint16_t local_rx_status:1;
+ uint16_t remote_rx_status:1;
+ uint16_t link_1000fdx:1;
+ uint16_t link_1000hdx:1;
+ uint16_t res:2;
+ uint16_t idle_err_cnt:8;
+#else
+ uint16_t idle_err_cnt:8;
+ uint16_t res:2;
+ uint16_t link_1000hdx:1;
+ uint16_t link_1000fdx:1;
+ uint16_t remote_rx_status:1;
+ uint16_t local_rx_status:1;
+ uint16_t ms_resolve:1;
+ uint16_t ms_config_fault:1;
+#endif
+ } bits;
+} mii_gsr_t, *p_mii_gsr_t;
+
+/*
+ * MII Register 15: Extended status register.
+ */
+typedef union _mii_esr {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t link_1000Xfdx:1;
+ uint16_t link_1000Xhdx:1;
+ uint16_t link_1000fdx:1;
+ uint16_t link_1000hdx:1;
+ uint16_t res:12;
+#else
+ uint16_t res:12;
+ uint16_t link_1000hdx:1;
+ uint16_t link_1000fdx:1;
+ uint16_t link_1000Xhdx:1;
+ uint16_t link_1000Xfdx:1;
+#endif
+ } bits;
+} mii_esr_t, *p_mii_esr_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_MII_H_ */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_n2_esr_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_n2_esr_hw.h
new file mode 100644
index 0000000000..3390233187
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_n2_esr_hw.h
@@ -0,0 +1,363 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_N2_ESR_HW_H
+#define _SYS_NXGE_NXGE_N2_ESR_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESR_N2_DEV_ADDR 0x1E
+#define ESR_N2_BASE 0x8000
+
+/*
+ * Definitions for TI WIZ6C2xxN2x0 Macro Family.
+ */
+
+/* Register Blocks base address */
+
+#define ESR_N2_PLL_REG_OFFSET 0
+#define ESR_N2_TEST_REG_OFFSET 0x004
+#define ESR_N2_TX_REG_OFFSET 0x100
+#define ESR_N2_TX_0_REG_OFFSET 0x100
+#define ESR_N2_TX_1_REG_OFFSET 0x104
+#define ESR_N2_TX_2_REG_OFFSET 0x108
+#define ESR_N2_TX_3_REG_OFFSET 0x10c
+#define ESR_N2_TX_4_REG_OFFSET 0x110
+#define ESR_N2_TX_5_REG_OFFSET 0x114
+#define ESR_N2_TX_6_REG_OFFSET 0x118
+#define ESR_N2_TX_7_REG_OFFSET 0x11c
+#define ESR_N2_RX_REG_OFFSET 0x120
+#define ESR_N2_RX_0_REG_OFFSET 0x120
+#define ESR_N2_RX_1_REG_OFFSET 0x124
+#define ESR_N2_RX_2_REG_OFFSET 0x128
+#define ESR_N2_RX_3_REG_OFFSET 0x12c
+#define ESR_N2_RX_4_REG_OFFSET 0x130
+#define ESR_N2_RX_5_REG_OFFSET 0x134
+#define ESR_N2_RX_6_REG_OFFSET 0x138
+#define ESR_N2_RX_7_REG_OFFSET 0x13c
+#define ESR_N2_P1_REG_OFFSET 0x400
+
+/* Register address */
+
+#define ESR_N2_PLL_CFG_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET
+#define ESR_N2_PLL_CFG_L_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET
+#define ESR_N2_PLL_CFG_H_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET + 1
+#define ESR_N2_PLL_STS_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET + 2
+#define ESR_N2_PLL_STS_L_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET + 2
+#define ESR_N2_PLL_STS_H_REG ESR_N2_BASE + ESR_N2_PLL_REG_OFFSET + 3
+#define ESR_N2_TEST_CFG_REG ESR_N2_BASE + ESR_N2_TEST_REG_OFFSET
+#define ESR_N2_TEST_CFG_L_REG ESR_N2_BASE + ESR_N2_TEST_REG_OFFSET
+#define ESR_N2_TEST_CFG_H_REG ESR_N2_BASE + ESR_N2_TEST_REG_OFFSET + 1
+
+#define ESR_N2_TX_CFG_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4))
+#define ESR_N2_TX_CFG_L_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4))
+#define ESR_N2_TX_CFG_H_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4) + 1)
+#define ESR_N2_TX_STS_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4) + 2)
+#define ESR_N2_TX_STS_L_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4) + 2)
+#define ESR_N2_TX_STS_H_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_TX_REG_OFFSET +\
+ (chan * 4) + 3)
+#define ESR_N2_RX_CFG_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4))
+#define ESR_N2_RX_CFG_L_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4))
+#define ESR_N2_RX_CFG_H_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4) + 1)
+#define ESR_N2_RX_STS_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4) + 2)
+#define ESR_N2_RX_STS_L_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4) + 2)
+#define ESR_N2_RX_STS_H_REG_ADDR(chan) (ESR_N2_BASE + ESR_N2_RX_REG_OFFSET +\
+ (chan * 4) + 3)
+
+/* PLL Configuration Low 16-bit word */
+typedef union _esr_ti_cfgpll_l {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res2 : 6;
+ uint16_t lb : 2;
+ uint16_t res1 : 3;
+ uint16_t mpy : 4;
+ uint16_t enpll : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t enpll : 1;
+ uint16_t mpy : 4;
+ uint16_t res1 : 3;
+ uint16_t lb : 2;
+ uint16_t res2 : 6;
+#endif
+ } bits;
+} esr_ti_cfgpll_l_t;
+
+/* PLL Configurations */
+#define CFGPLL_LB_FREQ_DEP_BANDWIDTH 0
+#define CFGPLL_LB_LOW_BANDWIDTH 0x2
+#define CFGPLL_LB_HIGH_BANDWIDTH 0x3
+#define CFGPLL_MPY_4X 0
+#define CFGPLL_MPY_5X 0x1
+#define CFGPLL_MPY_6X 0x2
+#define CFGPLL_MPY_8X 0x4
+#define CFGPLL_MPY_10X 0x5
+#define CFGPLL_MPY_12X 0x6
+#define CFGPLL_MPY_12P5X 0x7
+
+/* Rx Configuration Low 16-bit word */
+
+typedef union _esr_ti_cfgrx_l {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t los : 2;
+ uint16_t align : 2;
+ uint16_t res : 1;
+ uint16_t term : 3;
+ uint16_t invpair : 1;
+ uint16_t rate : 2;
+ uint16_t buswidth : 3;
+ uint16_t entest : 1;
+ uint16_t enrx : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t enrx : 1;
+ uint16_t entest : 1;
+ uint16_t buswidth : 3;
+ uint16_t rate : 2;
+ uint16_t invpair : 1;
+ uint16_t term : 3;
+ uint16_t res : 1;
+ uint16_t align : 2;
+ uint16_t los : 2;
+#endif
+ } bits;
+} esr_ti_cfgrx_l_t;
+
+/* Rx Configuration High 16-bit word */
+
+typedef union _esr_ti_cfgrx_h {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res2 : 6;
+ uint16_t bsinrxn : 1;
+ uint16_t bsinrxp : 1;
+ uint16_t res1 : 1;
+ uint16_t eq : 4;
+ uint16_t cdr : 3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t cdr : 3;
+ uint16_t eq : 4;
+ uint16_t res1 : 1;
+ uint16_t bsinrxp : 1;
+ uint16_t bsinrxn : 1;
+ uint16_t res2 : 6;
+#endif
+ } bits;
+} esr_ti_cfgrx_h_t;
+
+/* Receive Configurations */
+#define CFGRX_BUSWIDTH_10BIT 0
+#define CFGRX_BUSWIDTH_8BIT 1
+#define CFGRX_RATE_FULL 0
+#define CFGRX_RATE_HALF 1
+#define CFGRX_RATE_QUAD 2
+#define CFGRX_TERM_VDDT 0
+#define CFGRX_TERM_0P8VDDT 1
+#define CFGRX_TERM_FLOAT 3
+#define CFGRX_ALIGN_DIS 0
+#define CFGRX_ALIGN_EN 1
+#define CFGRX_ALIGN_JOG 2
+#define CFGRX_LOS_DIS 0
+#define CFGRX_LOS_HITHRES 1
+#define CFGRX_LOS_LOTHRES 2
+#define CFGRX_CDR_1ST_ORDER 0
+#define CFGRX_CDR_2ND_ORDER_HP 1
+#define CFGRX_CDR_2ND_ORDER_MP 2
+#define CFGRX_CDR_2ND_ORDER_LP 3
+#define CFGRX_CDR_1ST_ORDER_FAST_LOCK 4
+#define CFGRX_CDR_2ND_ORDER_HP_FAST_LOCK 5
+#define CFGRX_CDR_2ND_ORDER_MP_FAST_LOCK 6
+#define CFGRX_CDR_2ND_ORDER_LP_FAST_LOCK 7
+#define CFGRX_EQ_MAX_LF 0
+#define CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF 0x1
+#define CFGRX_EQ_ADAPTIVE_LF_1084MHZ_ZF 0x8
+#define CFGRX_EQ_ADAPTIVE_LF_805MHZ_ZF 0x9
+#define CFGRX_EQ_ADAPTIVE_LP_573MHZ_ZF 0xA
+#define CFGRX_EQ_ADAPTIVE_LP_402MHZ_ZF 0xB
+#define CFGRX_EQ_ADAPTIVE_LP_304MHZ_ZF 0xC
+#define CFGRX_EQ_ADAPTIVE_LP_216MHZ_ZF 0xD
+#define CFGRX_EQ_ADAPTIVE_LP_156MHZ_ZF 0xE
+#define CFGRX_EQ_ADAPTIVE_LP_135HZ_ZF 0xF
+
+/* Rx Status Low 16-bit word */
+
+typedef union _esr_ti_stsrx_l {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res : 10;
+ uint16_t bsrxn : 1;
+ uint16_t bsrxp : 1;
+ uint16_t losdtct : 1;
+ uint16_t oddcg : 1;
+ uint16_t sync : 1;
+ uint16_t testfail : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t testfail : 1;
+ uint16_t sync : 1;
+ uint16_t oddcg : 1;
+ uint16_t losdtct : 1;
+ uint16_t bsrxp : 1;
+ uint16_t bsrxn : 1;
+ uint16_t res : 10;
+#endif
+ } bits;
+} esr_ti_stsrx_l_t;
+
+/* Tx Configuration Low 16-bit word */
+
+typedef union _esr_ti_cfgtx_l {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t de : 4;
+ uint16_t swing : 3;
+ uint16_t cm : 1;
+ uint16_t invpair : 1;
+ uint16_t rate : 2;
+ uint16_t buswwidth : 3;
+ uint16_t entest : 1;
+ uint16_t entx : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t entx : 1;
+ uint16_t entest : 1;
+ uint16_t buswwidth : 3;
+ uint16_t rate : 2;
+ uint16_t invpair : 1;
+ uint16_t cm : 1;
+ uint16_t swing : 3;
+ uint16_t de : 4;
+#endif
+ } bits;
+} esr_ti_cfgtx_l_t;
+
+/* Tx Configuration High 16-bit word */
+
+typedef union _esr_ti_cfgtx_h {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res : 14;
+ uint16_t bstx : 1;
+ uint16_t enftp : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t enftp : 1;
+ uint16_t bstx : 1;
+ uint16_t res : 14;
+#endif
+ } bits;
+} esr_ti_cfgtx_h_t;
+
+/* Transmit Configurations */
+#define CFGTX_BUSWIDTH_10BIT 0
+#define CFGTX_BUSWIDTH_8BIT 1
+#define CFGTX_RATE_FULL 0
+#define CFGTX_RATE_HALF 1
+#define CFGTX_RATE_QUAD 2
+#define CFGTX_SWING_125MV 0
+#define CFGTX_SWING_250MV 1
+#define CFGTX_SWING_500MV 2
+#define CFGTX_SWING_625MV 3
+#define CFGTX_SWING_750MV 4
+#define CFGTX_SWING_1000MV 5
+#define CFGTX_SWING_1250MV 6
+#define CFGTX_SWING_1375MV 7
+#define CFGTX_DE_0 0
+#define CFGTX_DE_4P76 1
+#define CFGTX_DE_9P52 2
+#define CFGTX_DE_14P28 3
+#define CFGTX_DE_19P04 4
+#define CFGTX_DE_23P8 5
+#define CFGTX_DE_28P56 6
+#define CFGTX_DE_33P32 7
+
+/* Test Configuration */
+
+typedef union _esr_ti_testcfg {
+ uint16_t value;
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 1;
+ uint16_t invpat : 1;
+ uint16_t rate : 2;
+ uint16_t res : 1;
+ uint16_t enbspls : 1;
+ uint16_t enbsrx : 1;
+ uint16_t enbstx : 1;
+ uint16_t loopback : 2;
+ uint16_t clkbyp : 2;
+ uint16_t enrxpatt : 1;
+ uint16_t entxpatt : 1;
+ uint16_t testpatt : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t testpatt : 2;
+ uint16_t entxpatt : 1;
+ uint16_t enrxpatt : 1;
+ uint16_t clkbyp : 2;
+ uint16_t loopback : 2;
+ uint16_t enbstx : 1;
+ uint16_t enbsrx : 1;
+ uint16_t enbspls : 1;
+ uint16_t res : 1;
+ uint16_t rate : 2;
+ uint16_t invpat : 1;
+ uint16_t res1 : 1;
+#endif
+ } bits;
+} esr_ti_testcfg_t;
+
+#define TESTCFG_PAD_LOOPBACK 0x1
+#define TESTCFG_INNER_CML_DIS_LOOPBACK 0x2
+#define TESTCFG_INNER_CML_EN_LOOOPBACK 0x3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_N2_ESR_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_phy_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_phy_hw.h
new file mode 100644
index 0000000000..c1ae1d883b
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_phy_hw.h
@@ -0,0 +1,633 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_PHY_HW_H
+#define _SYS_NXGE_NXGE_PHY_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+#define BCM5464_NEPTUNE_PORT_ADDR_BASE 10
+#define BCM8704_NEPTUNE_PORT_ADDR_BASE 8
+#define BCM8704_N2_PORT_ADDR_BASE 16
+#define BCM8704_PMA_PMD_DEV_ADDR 1
+#define BCM8704_PCS_DEV_ADDR 3
+#define BCM8704_USER_DEV3_ADDR 3
+#define BCM8704_PHYXS_ADDR 4
+#define BCM8704_USER_DEV4_ADDR 4
+
+/* Definitions for BCM 5464R PHY chip */
+
+#define BCM5464R_PHY_ECR 16
+#define BCM5464R_PHY_ESR 17
+#define BCM5464R_RXERR_CNT 18
+#define BCM5464R_FALSECS_CNT 19
+#define BCM5464R_RX_NOTOK_CNT 20
+#define BCM5464R_ER_DATA 21
+#define BCM5464R_RES 22
+#define BCM5464R_ER_ACC 23
+#define BCM5464R_AUX_CTL 24
+#define BCM5464R_AUX_S 25
+#define BCM5464R_INTR_S 26
+#define BCM5464R_INTR_M 27
+#define BCM5464R_MISC 28
+#define BCM5464R_MISC1 29
+#define BCM5464R_TESTR1 30
+
+#define PHY_BCM_5464R_OUI 0x001018
+#define PHY_BCM_5464R_MODEL 0x0B
+
+/*
+ * MII Register 16: PHY Extended Control Register
+ */
+
+typedef union _mii_phy_ecr_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t mac_phy_if_mode : 1;
+ uint16_t dis_automdicross : 1;
+ uint16_t tx_dis : 1;
+ uint16_t intr_dis : 1;
+ uint16_t force_intr : 1;
+ uint16_t bypass_encdec : 1;
+ uint16_t bypass_scrdes : 1;
+ uint16_t bypass_mlt3 : 1;
+ uint16_t bypass_rx_sym : 1;
+ uint16_t reset_scr : 1;
+ uint16_t en_led_traffic : 1;
+ uint16_t force_leds_on : 1;
+ uint16_t force_leds_off : 1;
+ uint16_t res : 2;
+ uint16_t gmii_fifo_elas : 1;
+#else
+ uint16_t gmii_fifo_elas : 1;
+ uint16_t res : 2;
+ uint16_t force_leds_off : 1;
+ uint16_t force_leds_on : 1;
+ uint16_t en_led_traffic : 1;
+ uint16_t reset_scr : 1;
+ uint16_t bypass_rx_sym : 1;
+ uint16_t bypass_mlt3 : 1;
+ uint16_t bypass_scrdes : 1;
+ uint16_t bypass_encdec : 1;
+ uint16_t force_intr : 1;
+ uint16_t intr_dis : 1;
+ uint16_t tx_dis : 1;
+ uint16_t dis_automdicross : 1;
+ uint16_t mac_phy_if_mode : 1;
+#endif
+ } bits;
+} mii_phy_ecr_t, *p_mii_phy_ecr_t;
+
+/*
+ * MII Register 17: PHY Extended Status Register
+ */
+typedef union _mii_phy_esr_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t anbpsfm : 1;
+ uint16_t wsdwngr : 1;
+ uint16_t mdi_crst : 1;
+ uint16_t intr_s : 1;
+ uint16_t rmt_rx_s : 1;
+ uint16_t loc_rx_s : 1;
+ uint16_t locked : 1;
+ uint16_t link_s : 1;
+ uint16_t crc_err : 1;
+ uint16_t cext_err : 1;
+ uint16_t bad_ssd : 1;
+ uint16_t bad_esd : 1;
+ uint16_t rx_err : 1;
+ uint16_t tx_err : 1;
+ uint16_t lock_err : 1;
+ uint16_t mlt3_cerr : 1;
+#else
+ uint16_t mlt3_cerr : 1;
+ uint16_t lock_err : 1;
+ uint16_t tx_err : 1;
+ uint16_t rx_err : 1;
+ uint16_t bad_esd : 1;
+ uint16_t bad_ssd : 1;
+ uint16_t cext_err : 1;
+ uint16_t crc_err : 1;
+ uint16_t link_s : 1;
+ uint16_t locked : 1;
+ uint16_t loc_rx_s : 1;
+ uint16_t rmt_rx_s : 1;
+ uint16_t intr_s : 1;
+ uint16_t mdi_crst : 1;
+ uint16_t wsdwngr : 1;
+ uint16_t anbpsfm : 1;
+#endif
+ } bits;
+} mii_phy_esr_t, *p_mii_phy_esr_t;
+
+/*
+ * MII Register 18: Receive Error Counter Register
+ */
+typedef union _mii_rxerr_cnt_t {
+ uint16_t value;
+ struct {
+ uint16_t rx_err_cnt : 16;
+ } bits;
+} mii_rxerr_cnt_t, *p_mii_rxerr_cnt_t;
+
+/*
+ * MII Register 19: False Carrier Sense Counter Register
+ */
+typedef union _mii_falsecs_cnt_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t res : 8;
+ uint16_t false_cs_cnt : 8;
+#else
+ uint16_t false_cs_cnt : 8;
+ uint16_t res : 8;
+#endif
+ } bits;
+} mii_falsecs_cnt_t, *p_mii_falsecs_cnt_t;
+
+/*
+ * MII Register 20: Receiver NOT_OK Counter Register
+ */
+typedef union _mii_rx_notok_cnt_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t l_rx_notok_cnt : 8;
+ uint16_t r_rx_notok_cnt : 8;
+#else
+ uint16_t r_rx_notok_cnt : 8;
+ uint16_t l_rx_notok_cnt : 8;
+#endif
+ } bits;
+} mii_rx_notok_cnt_t, *p_mii_rx_notok_t;
+
+/*
+ * MII Register 21: Expansion Register Data Register
+ */
+typedef union _mii_er_data_t {
+ uint16_t value;
+ struct {
+ uint16_t reg_data;
+ } bits;
+} mii_er_data_t, *p_mii_er_data_t;
+
+/*
+ * MII Register 23: Expansion Register Access Register
+ */
+typedef union _mii_er_acc_t {
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t res : 4;
+ uint16_t er_sel : 4;
+ uint16_t er_acc : 8;
+#else
+ uint16_t er_acc : 8;
+ uint16_t er_sel : 4;
+ uint16_t res : 4;
+#endif
+ } bits;
+} mii_er_acc_t, *p_mii_er_acc_t;
+
+#define EXP_RXTX_PKT_CNT 0x0
+#define EXP_INTR_STAT 0x1
+#define MULTICOL_LED_SEL 0x4
+#define MULTICOL_LED_FLASH_RATE_CTL 0x5
+#define MULTICOL_LED_BLINK_CTL 0x6
+#define CABLE_DIAG_CTL 0x10
+#define CABLE_DIAG_RES 0x11
+#define CABLE_DIAG_LEN_CH_2_1 0x12
+#define CABLE_DIAG_LEN_CH_4_3 0x13
+
+/*
+ * MII Register 24: Auxiliary Control Register
+ */
+typedef union _mii_aux_ctl_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t ext_lb : 1;
+ uint16_t ext_pkt_len : 1;
+ uint16_t edge_rate_ctl_1000 : 2;
+ uint16_t res : 1;
+ uint16_t write_1 : 1;
+ uint16_t res1 : 2;
+ uint16_t dis_partial_resp : 1;
+ uint16_t res2 : 1;
+ uint16_t edge_rate_ctl_100 : 2;
+ uint16_t diag_mode : 1;
+ uint16_t shadow_reg_sel : 3;
+#else
+ uint16_t shadow_reg_sel : 3;
+ uint16_t diag_mode : 1;
+ uint16_t edge_rate_ctl_100 : 2;
+ uint16_t res2 : 1;
+ uint16_t dis_partial_resp : 1;
+ uint16_t res1 : 2;
+ uint16_t write_1 : 1;
+ uint16_t res : 1;
+ uint16_t edge_rate_ctl_1000 : 2;
+ uint16_t ext_pkt_len : 1;
+ uint16_t ext_lb : 1;
+#endif
+ } bits;
+} mii_aux_ctl_t, *p_mii_aux_ctl_t;
+
+#define AUX_REG 0x0
+#define AUX_10BASET 0x1
+#define AUX_PWR_CTL 0x2
+#define AUX_MISC_TEST 0x4
+#define AUX_MISC_CTL 0x7
+
+/*
+ * MII Register 25: Auxiliary Status Summary Register
+ */
+typedef union _mii_aux_s_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t an_complete : 1;
+ uint16_t an_complete_ack : 1;
+ uint16_t an_ack_detect : 1;
+ uint16_t an_ability_detect : 1;
+ uint16_t an_np_wait : 1;
+ uint16_t an_hcd : 3;
+ uint16_t pd_fault : 1;
+ uint16_t rmt_fault : 1;
+ uint16_t an_page_rx : 1;
+ uint16_t lp_an_ability : 1;
+ uint16_t lp_np_ability : 1;
+ uint16_t link_s : 1;
+ uint16_t pause_res_rx_dir : 1;
+ uint16_t pause_res_tx_dir : 1;
+#else
+ uint16_t pause_res_tx_dir : 1;
+ uint16_t pause_res_rx_dir : 1;
+ uint16_t link_s : 1;
+ uint16_t lp_np_ability : 1;
+ uint16_t lp_an_ability : 1;
+ uint16_t an_page_rx : 1;
+ uint16_t rmt_fault : 1;
+ uint16_t pd_fault : 1;
+ uint16_t an_hcd : 3;
+ uint16_t an_np_wait : 1;
+ uint16_t an_ability_detect : 1;
+ uint16_t an_ack_detect : 1;
+ uint16_t an_complete_ack : 1;
+ uint16_t an_complete : 1;
+#endif
+ } bits;
+} mii_aux_s_t, *p_mii_aux_s_t;
+
+/*
+ * MII Register 26, 27: Interrupt Status and Mask Registers
+ */
+typedef union _mii_intr_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t res : 1;
+ uint16_t illegal_pair_swap : 1;
+ uint16_t mdix_status_change : 1;
+ uint16_t exceed_hicnt_thres : 1;
+ uint16_t exceed_locnt_thres : 1;
+ uint16_t an_page_rx : 1;
+ uint16_t hcd_nolink : 1;
+ uint16_t no_hcd : 1;
+ uint16_t neg_unsupported_hcd : 1;
+ uint16_t scr_sync_err : 1;
+ uint16_t rmt_rx_status_change : 1;
+ uint16_t loc_rx_status_change : 1;
+ uint16_t duplex_mode_change : 1;
+ uint16_t link_speed_change : 1;
+ uint16_t link_status_change : 1;
+ uint16_t crc_err : 1;
+#else
+ uint16_t crc_err : 1;
+ uint16_t link_status_change : 1;
+ uint16_t link_speed_change : 1;
+ uint16_t duplex_mode_change : 1;
+ uint16_t loc_rx_status_change : 1;
+ uint16_t rmt_rx_status_change : 1;
+ uint16_t scr_sync_err : 1;
+ uint16_t neg_unsupported_hcd : 1;
+ uint16_t no_hcd : 1;
+ uint16_t hcd_nolink : 1;
+ uint16_t an_page_rx : 1;
+ uint16_t exceed_locnt_thres : 1;
+ uint16_t exceed_hicnt_thres : 1;
+ uint16_t mdix_status_change : 1;
+ uint16_t illegal_pair_swap : 1;
+ uint16_t res : 1;
+#endif
+ } bits;
+} mii_intr_t, *p_mii_intr_t;
+
+/*
+ * MII Register 28: Register 1C Access Register
+ */
+typedef union _mii_misc_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t w_en : 1;
+ uint16_t shadow_reg_sel : 5;
+ uint16_t data : 10;
+#else
+ uint16_t data : 10;
+ uint16_t shadow_reg_sel : 5;
+ uint16_t w_en : 1;
+#endif
+ } bits;
+} mii_misc_t, *p_mii_misc_t;
+
+#define LINK_LED_MODE 0x2
+#define CLK_ALIGN_CTL 0x3
+#define WIRE_SP_RETRY 0x4
+#define CLK125 0x5
+#define LED_STATUS 0x8
+#define LED_CONTROL 0x9
+#define AUTO_PWR_DOWN 0xA
+#define LED_SEL1 0xD
+#define LED_SEL2 0xE
+
+/*
+ * MII Register 29: Master/Slave Seed / HCD Status Register
+ */
+
+typedef union _mii_misc1_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t en_shadow_reg : 1;
+ uint16_t data : 15;
+#else
+ uint16_t data : 15;
+ uint16_t en_shadow_reg : 1;
+#endif
+ } bits;
+} mii_misc1_t, *p_mii_misc1_t;
+
+/*
+ * MII Register 30: Test Register 1
+ */
+
+typedef union _mii_test1_t {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t crc_err_cnt_sel : 1;
+ uint16_t res : 7;
+ uint16_t manual_swap_mdi_st : 1;
+ uint16_t res1 : 7;
+#else
+ uint16_t res1 : 7;
+ uint16_t manual_swap_mdi_st : 1;
+ uint16_t res : 7;
+ uint16_t crc_err_cnt_sel : 1;
+#endif
+ } bits;
+} mii_test1_t, *p_mii_test1_t;
+
+
+/* Definitions of BCM8704 */
+
+#define BCM8704_PMD_CONTROL_REG 0
+#define BCM8704_PMD_STATUS_REG 0x1
+#define BCM8704_PMD_ID_0_REG 0x2
+#define BCM8704_PMD_ID_1_REG 0x3
+#define BCM8704_PMD_SPEED_ABIL_REG 0x4
+#define BCM8704_PMD_DEV_IN_PKG1_REG 0x5
+#define BCM8704_PMD_DEV_IN_PKG2_REG 0x6
+#define BCM8704_PMD_CONTROL2_REG 0x7
+#define BCM8704_PMD_STATUS2_REG 0x8
+#define BCM8704_PMD_TRANSMIT_DIS_REG 0x9
+#define BCM8704_PMD_RECEIVE_SIG_DETECT 0xa
+#define BCM8704_PMD_ORG_UNIQUE_ID_0_REG 0xe
+#define BCM8704_PMD_ORG_UNIQUE_ID_1_REG 0xf
+#define BCM8704_PCS_CONTROL_REG 0
+#define BCM8704_PCS_STATUS1_REG 0x1
+#define BCM8704_PCS_ID_0_REG 0x2
+#define BCM8704_PCS_ID_1_REG 0x3
+#define BCM8704_PCS_SPEED_ABILITY_REG 0x4
+#define BCM8704_PCS_DEV_IN_PKG1_REG 0x5
+#define BCM8704_PCS_DEV_IN_PKG2_REG 0x6
+#define BCM8704_PCS_CONTROL2_REG 0x7
+#define BCM8704_PCS_STATUS2_REG 0x8
+#define BCM8704_PCS_ORG_UNIQUE_ID_0_REG 0xe
+#define BCM8704_PCS_ORG_UNIQUE_ID_1_REG 0xf
+#define BCM8704_PCS_STATUS_REG 0x18
+#define BCM8704_10GBASE_R_PCS_STATUS_REG 0x20
+#define BCM8704_10GBASE_R_PCS_STATUS2_REG 0x21
+#define BCM8704_PHYXS_CONTROL_REG 0
+#define BCM8704_PHYXS_STATUS_REG 0x1
+#define BCM8704_PHY_ID_0_REG 0x2
+#define BCM8704_PHY_ID_1_REG 0x3
+#define BCM8704_PHYXS_SPEED_ABILITY_REG 0x4
+#define BCM8704_PHYXS_DEV_IN_PKG2_REG 0x5
+#define BCM8704_PHYXS_DEV_IN_PKG1_REG 0x6
+#define BCM8704_PHYXS_STATUS2_REG 0x8
+#define BCM8704_PHYXS_ORG_UNIQUE_ID_0_REG 0xe
+#define BCM8704_PHYXS_ORG_UNIQUE_ID_1_REG 0xf
+#define BCM8704_PHYXS_XGXS_LANE_STATUS_REG 0x18
+#define BCM8704_PHYXS_XGXS_TEST_CONTROL_REG 0x19
+#define BCM8704_USER_CONTROL_REG 0xC800
+#define BCM8704_USER_ANALOG_CLK_REG 0xC801
+#define BCM8704_USER_PMD_RX_CONTROL_REG 0xC802
+#define BCM8704_USER_PMD_TX_CONTROL_REG 0xC803
+#define BCM8704_USER_ANALOG_STATUS0_REG 0xC804
+#define BCM8704_USER_OPTICS_DIGITAL_CTRL_REG 0xC808
+#define BCM8704_USER_RX2_CONTROL1_REG 0x80C6
+#define BCM8704_USER_RX1_CONTROL1_REG 0x80D6
+#define BCM8704_USER_RX0_CONTROL1_REG 0x80E6
+#define BCM8704_USER_TX_ALARM_STATUS_REG 0x9004
+
+/* Rx Channel Control1 Register bits */
+#define BCM8704_RXPOL_FLIP 0x20
+
+typedef union _phyxs_control {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t reset : 1;
+ uint16_t loopback : 1;
+ uint16_t speed_sel2 : 1;
+ uint16_t res2 : 1;
+ uint16_t low_power : 1;
+ uint16_t res1 : 4;
+ uint16_t speed_sel1 : 1;
+ uint16_t speed_sel0 : 4;
+ uint16_t res0 : 2;
+#else
+ uint16_t res0 : 2;
+ uint16_t speed_sel0 : 4;
+ uint16_t speed_sel1 : 1;
+ uint16_t res1 : 4;
+ uint16_t low_power : 1;
+ uint16_t res2 : 1;
+ uint16_t speed_sel2 : 1;
+ uint16_t loopback : 1;
+ uint16_t reset : 1;
+#endif
+ } bits;
+} phyxs_control_t, *p_phyxs_control_t, pcs_control_t, *p_pcs_control_t;
+
+
+/* PMD/Optics Digital Control Register (Dev=3 Addr=0xc800) */
+
+typedef union _control {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t optxenb_lvl : 1;
+ uint16_t optxrst_lvl : 1;
+ uint16_t opbiasflt_lvl : 1;
+ uint16_t obtmpflt_lvl : 1;
+ uint16_t opprflt_lvl : 1;
+ uint16_t optxflt_lvl : 1;
+ uint16_t optrxlos_lvl : 1;
+ uint16_t oprxflt_lvl : 1;
+ uint16_t optxon_lvl : 1;
+ uint16_t res1 : 7;
+#else
+ uint16_t res1 : 7;
+ uint16_t optxon_lvl : 1;
+ uint16_t oprxflt_lvl : 1;
+ uint16_t optrxlos_lvl : 1;
+ uint16_t optxflt_lvl : 1;
+ uint16_t opprflt_lvl : 1;
+ uint16_t obtmpflt_lvl : 1;
+ uint16_t opbiasflt_lvl : 1;
+ uint16_t optxrst_lvl : 1;
+ uint16_t optxenb_lvl : 1;
+#endif
+ } bits;
+} control_t, *p_control_t;
+
+typedef union _pmd_tx_control {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t res1 : 7;
+ uint16_t xfp_clken : 1;
+ uint16_t tx_dac_txd : 2;
+ uint16_t tx_dac_txck : 2;
+ uint16_t tsd_lpwren : 1;
+ uint16_t tsck_lpwren : 1;
+ uint16_t cmu_lpwren : 1;
+ uint16_t sfiforst : 1;
+#else
+ uint16_t sfiforst : 1;
+ uint16_t cmu_lpwren : 1;
+ uint16_t tsck_lpwren : 1;
+ uint16_t tsd_lpwren : 1;
+ uint16_t tx_dac_txck : 2;
+ uint16_t tx_dac_txd : 2;
+ uint16_t xfp_clken : 1;
+ uint16_t res1 : 7;
+#endif
+ } bits;
+} pmd_tx_control_t, *p_pmd_tx_control_t;
+
+
+/* PMD/Optics Digital Control Register (Dev=3 Addr=0xc808) */
+
+
+/* PMD/Optics Digital Control Register (Dev=3 Addr=0xc808) */
+
+typedef union _optics_dcntr {
+ uint16_t value;
+ struct {
+#ifdef _BIT_FIELDS_HTOL
+ uint16_t fault_mode : 1;
+ uint16_t tx_pwrdown : 1;
+ uint16_t rx_pwrdown : 1;
+ uint16_t ext_flt_en : 1;
+ uint16_t opt_rst : 1;
+ uint16_t pcs_tx_inv_b : 1;
+ uint16_t pcs_rx_inv : 1;
+ uint16_t res3 : 2;
+ uint16_t gpio_sel : 2;
+ uint16_t res2 : 1;
+ uint16_t lpbk_err_dis : 1;
+ uint16_t res1 : 2;
+ uint16_t txonoff_pwdwn_dis : 1;
+#else
+ uint16_t txonoff_pwdwn_dis : 1;
+ uint16_t res1 : 2;
+ uint16_t lpbk_err_dis : 1;
+ uint16_t res2 : 1;
+ uint16_t gpio_sel : 2;
+ uint16_t res3 : 2;
+ uint16_t pcs_rx_inv : 1;
+ uint16_t pcs_tx_inv_b : 1;
+ uint16_t opt_rst : 1;
+ uint16_t ext_flt_en : 1;
+ uint16_t rx_pwrdown : 1;
+ uint16_t tx_pwrdown : 1;
+ uint16_t fault_mode : 1;
+#endif
+ } bits;
+} optics_dcntr_t, *p_optics_dcntr_t;
+
+/* PMD Receive Signal Detect Register (Dev = 1 Register Address = 0x000A) */
+
+#define PMD_RX_SIG_DET3 0x10
+#define PMD_RX_SIG_DET2 0x08
+#define PMD_RX_SIG_DET1 0x04
+#define PMD_RX_SIG_DET0 0x02
+#define GLOB_PMD_RX_SIG_OK 0x01
+
+/* 10GBase-R PCS Status Register (Dev = 3, Register Address = 0x0020) */
+
+#define PCS_10GBASE_RX_LINK_STATUS 0x1000
+#define PCS_PRBS31_ABLE 0x0004
+#define PCS_10GBASE_R_HI_BER 0x0002
+#define PCS_10GBASE_R_PCS_BLK_LOCK 0x0001
+
+/* XGXS Lane Status Register (Dev = 4, Register Address = 0x0018) */
+
+#define XGXS_LANE_ALIGN_STATUS 0x1000
+#define XGXS_PATTERN_TEST_ABILITY 0x0800
+#define XGXS_LANE3_SYNC 0x0008
+#define XGXS_LANE2_SYNC 0x0004
+#define XGXS_LANE1_SYNC 0x0002
+#define XGXS_LANE0_SYNC 0x0001
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_PHY_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_rxdma.h b/usr/src/uts/sun4v/sys/nxge/nxge_rxdma.h
new file mode 100644
index 0000000000..04bb82ad1f
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_rxdma.h
@@ -0,0 +1,462 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_RXDMA_H
+#define _SYS_NXGE_NXGE_RXDMA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/nxge/nxge_rxdma_hw.h>
+#include <npi_rxdma.h>
+
+#define RXDMA_CK_DIV_DEFAULT 7500 /* 25 usec */
+/*
+ * Hardware RDC designer: 8 cache lines during Atlas bringup.
+ */
+#define RXDMA_RED_LESS_BYTES (8 * 64) /* 8 cache line */
+#define RXDMA_RED_LESS_ENTRIES (RXDMA_RED_LESS_BYTES/8)
+#define RXDMA_RED_WINDOW_DEFAULT 0
+#define RXDMA_RED_THRES_DEFAULT 0
+
+#define RXDMA_RCR_PTHRES_DEFAULT 0x20
+#define RXDMA_RCR_TO_DEFAULT 0x8
+
+/*
+ * hardware workarounds: kick 16 (was 8 before)
+ */
+#define NXGE_RXDMA_POST_BATCH 16
+
+#define RXBUF_START_ADDR(a, index, bsize) ((a & (index * bsize))
+#define RXBUF_OFFSET_FROM_START(a, start) (start - a)
+#define RXBUF_64B_ALIGNED 64
+
+#define NXGE_RXBUF_EXTRA 34
+/*
+ * Receive buffer thresholds and buffer types
+ */
+#define NXGE_RX_BCOPY_SCALE 8 /* use 1/8 as lowest granularity */
+typedef enum {
+ NXGE_RX_COPY_ALL = 0, /* do bcopy on every packet */
+ NXGE_RX_COPY_1, /* bcopy on 1/8 of buffer posted */
+ NXGE_RX_COPY_2, /* bcopy on 2/8 of buffer posted */
+ NXGE_RX_COPY_3, /* bcopy on 3/8 of buffer posted */
+ NXGE_RX_COPY_4, /* bcopy on 4/8 of buffer posted */
+ NXGE_RX_COPY_5, /* bcopy on 5/8 of buffer posted */
+ NXGE_RX_COPY_6, /* bcopy on 6/8 of buffer posted */
+ NXGE_RX_COPY_7, /* bcopy on 7/8 of buffer posted */
+ NXGE_RX_COPY_NONE /* don't do bcopy at all */
+} nxge_rxbuf_threshold_t;
+
+typedef enum {
+ NXGE_RBR_TYPE0 = RCR_PKTBUFSZ_0, /* bcopy buffer size 0 (small) */
+ NXGE_RBR_TYPE1 = RCR_PKTBUFSZ_1, /* bcopy buffer size 1 (medium) */
+ NXGE_RBR_TYPE2 = RCR_PKTBUFSZ_2 /* bcopy buffer size 2 (large) */
+} nxge_rxbuf_type_t;
+
+typedef struct _rdc_errlog {
+ rdmc_par_err_log_t pre_par;
+ rdmc_par_err_log_t sha_par;
+ uint8_t compl_err_type;
+} rdc_errlog_t;
+
+/*
+ * Receive Statistics.
+ */
+typedef struct _nxge_rx_ring_stats_t {
+ uint64_t ipackets;
+ uint64_t ibytes;
+ uint32_t ierrors;
+ uint32_t multircv;
+ uint32_t brdcstrcv;
+ uint32_t norcvbuf;
+
+ uint32_t rx_inits;
+ uint32_t rx_jumbo_pkts;
+ uint32_t rx_multi_pkts;
+ uint32_t rx_mtu_pkts;
+ uint32_t rx_no_buf;
+
+ /*
+ * Receive buffer management statistics.
+ */
+ uint32_t rx_new_pages;
+ uint32_t rx_new_mtu_pgs;
+ uint32_t rx_new_nxt_pgs;
+ uint32_t rx_reused_pgs;
+ uint32_t rx_mtu_drops;
+ uint32_t rx_nxt_drops;
+
+ /*
+ * Error event stats.
+ */
+ uint32_t rx_rbr_tmout;
+ uint32_t l2_err;
+ uint32_t l4_cksum_err;
+ uint32_t fflp_soft_err;
+ uint32_t zcp_soft_err;
+ uint32_t dcf_err;
+ uint32_t rbr_tmout;
+ uint32_t rsp_cnt_err;
+ uint32_t byte_en_err;
+ uint32_t byte_en_bus;
+ uint32_t rsp_dat_err;
+ uint32_t rcr_ack_err;
+ uint32_t dc_fifo_err;
+ uint32_t rcr_sha_par;
+ uint32_t rbr_pre_par;
+ uint32_t port_drop_pkt;
+ uint32_t wred_drop;
+ uint32_t rbr_pre_empty;
+ uint32_t rcr_shadow_full;
+ uint32_t config_err;
+ uint32_t rcrincon;
+ uint32_t rcrfull;
+ uint32_t rbr_empty;
+ uint32_t rbrfull;
+ uint32_t rbrlogpage;
+ uint32_t cfiglogpage;
+ uint32_t rcrto;
+ uint32_t rcrthres;
+ uint32_t mex;
+ rdc_errlog_t errlog;
+} nxge_rx_ring_stats_t, *p_nxge_rx_ring_stats_t;
+
+typedef struct _nxge_rdc_sys_stats {
+ uint32_t pre_par;
+ uint32_t sha_par;
+ uint32_t id_mismatch;
+ uint32_t ipp_eop_err;
+ uint32_t zcp_eop_err;
+} nxge_rdc_sys_stats_t, *p_nxge_rdc_sys_stats_t;
+
+/*
+ * Software reserved buffer offset
+ */
+typedef struct _nxge_rxbuf_off_hdr_t {
+ uint32_t index;
+} nxge_rxbuf_off_hdr_t, *p_nxge_rxbuf_off_hdr_t;
+
+/*
+ * Definitions for each receive buffer block.
+ */
+typedef struct _nxge_rbb_t {
+ nxge_os_dma_common_t dma_buf_info;
+ uint8_t rbr_page_num;
+ uint32_t block_size;
+ uint16_t dma_channel;
+ uint32_t bytes_received;
+ uint32_t ref_cnt;
+ uint_t pkt_buf_size;
+ uint_t max_pkt_bufs;
+ uint32_t cur_usage_cnt;
+} nxge_rbb_t, *p_nxge_rbb_t;
+
+
+typedef struct _rx_tx_param_t {
+ nxge_logical_page_t logical_pages[NXGE_MAX_LOGICAL_PAGES];
+} rx_tx_param_t, *p_rx_tx_param_t;
+
+typedef struct _rx_tx_params {
+ struct _tx_param_t *tx_param_p;
+} rx_tx_params_t, *p_rx_tx_params_t;
+
+
+typedef struct _rx_msg_t {
+ nxge_os_dma_common_t buf_dma;
+ nxge_os_mutex_t lock;
+ struct _nxge_t *nxgep;
+ struct _rx_rbr_ring_t *rx_rbr_p;
+ boolean_t spare_in_use;
+ boolean_t free;
+ uint32_t ref_cnt;
+#ifdef RXBUFF_USE_SEPARATE_UP_CNTR
+ uint32_t pass_up_cnt;
+ boolean_t release;
+#endif
+ nxge_os_frtn_t freeb;
+ size_t bytes_arrived;
+ size_t bytes_expected;
+ size_t block_size;
+ uint32_t block_index;
+ uint32_t pkt_buf_size;
+ uint32_t pkt_buf_size_code;
+ uint32_t max_pkt_bufs;
+ uint32_t cur_usage_cnt;
+ uint32_t max_usage_cnt;
+ uchar_t *buffer;
+ uint32_t pri;
+ uint32_t shifted_addr;
+ boolean_t use_buf_pool;
+ p_mblk_t rx_mblk_p;
+ boolean_t rx_use_bcopy;
+} rx_msg_t, *p_rx_msg_t;
+
+typedef struct _rx_dma_handle_t {
+ nxge_os_dma_handle_t dma_handle; /* DMA handle */
+ nxge_os_acc_handle_t acc_handle; /* DMA memory handle */
+ npi_handle_t npi_handle;
+} rx_dma_handle_t, *p_rx_dma_handle_t;
+
+#define RXCOMP_HIST_ELEMENTS 100000
+
+typedef struct _nxge_rxcomphist_t {
+ uint_t comp_cnt;
+ uint64_t rx_comp_entry;
+} nxge_rxcomphist_t, *p_nxge_rxcomphist_t;
+
+/* Receive Completion Ring */
+typedef struct _rx_rcr_ring_t {
+ nxge_os_dma_common_t rcr_desc;
+ uint8_t rcr_page_num;
+ uint8_t rcr_buf_page_num;
+
+ struct _nxge_t *nxgep;
+
+ p_nxge_rx_ring_stats_t rdc_stats;
+
+ rcrcfig_a_t rcr_cfga;
+ rcrcfig_b_t rcr_cfgb;
+ boolean_t cfg_set;
+
+ nxge_os_mutex_t lock;
+ uint16_t index;
+ uint16_t rdc;
+ uint16_t rdc_grp_id;
+ uint16_t ldg_group_id;
+ boolean_t full_hdr_flag; /* 1: 18 bytes header */
+ uint16_t sw_priv_hdr_len; /* 0 - 192 bytes (SW) */
+ uint32_t comp_size; /* # of RCR entries */
+ uint64_t rcr_addr;
+ uint_t comp_wrap_mask;
+ uint_t comp_rd_index;
+ uint_t comp_wt_index;
+
+ p_rcr_entry_t rcr_desc_first_p;
+ p_rcr_entry_t rcr_desc_first_pp;
+ p_rcr_entry_t rcr_desc_last_p;
+ p_rcr_entry_t rcr_desc_last_pp;
+
+ p_rcr_entry_t rcr_desc_rd_head_p; /* software next read */
+ p_rcr_entry_t rcr_desc_rd_head_pp;
+
+ p_rcr_entry_t rcr_desc_wt_tail_p; /* hardware write */
+ p_rcr_entry_t rcr_desc_wt_tail_pp;
+
+ uint64_t rcr_tail_pp;
+ uint64_t rcr_head_pp;
+ struct _rx_rbr_ring_t *rx_rbr_p;
+ uint64_t max_receive_pkts;
+ p_mblk_t rx_first_mp;
+ mac_resource_handle_t rcr_mac_handle;
+} rx_rcr_ring_t, *p_rx_rcr_ring_t;
+
+
+
+/* Buffer index information */
+typedef struct _rxbuf_index_info_t {
+ uint32_t buf_index;
+ uint32_t start_index;
+ uint32_t buf_size;
+ uint64_t dvma_addr;
+ uint64_t kaddr;
+} rxbuf_index_info_t, *p_rxbuf_index_info_t;
+
+/* Buffer index information */
+
+typedef struct _rxring_info_t {
+ uint32_t hint[3];
+ uint32_t block_size_mask;
+ uint16_t max_iterations;
+ rxbuf_index_info_t buffer[NXGE_DMA_BLOCK];
+} rxring_info_t, *p_rxring_info_t;
+
+
+/* Receive Buffer Block Ring */
+typedef struct _rx_rbr_ring_t {
+ nxge_os_dma_common_t rbr_desc;
+ p_rx_msg_t *rx_msg_ring;
+ p_nxge_dma_common_t *dma_bufp;
+ rbr_cfig_a_t rbr_cfga;
+ rbr_cfig_b_t rbr_cfgb;
+ rbr_kick_t rbr_kick;
+ log_page_vld_t page_valid;
+ log_page_mask_t page_mask_1;
+ log_page_mask_t page_mask_2;
+ log_page_value_t page_value_1;
+ log_page_value_t page_value_2;
+ log_page_relo_t page_reloc_1;
+ log_page_relo_t page_reloc_2;
+ log_page_hdl_t page_hdl;
+
+ boolean_t cfg_set;
+
+ nxge_os_mutex_t lock;
+ nxge_os_mutex_t post_lock;
+ uint16_t index;
+ struct _nxge_t *nxgep;
+ uint16_t rdc;
+ uint16_t rdc_grp_id;
+ uint_t rbr_max_size;
+ uint64_t rbr_addr;
+ uint_t rbr_wrap_mask;
+ uint_t rbb_max;
+ uint_t rbb_added;
+ uint_t block_size;
+ uint_t num_blocks;
+ uint_t tnblocks;
+ uint_t pkt_buf_size0;
+ uint_t pkt_buf_size0_bytes;
+ uint_t npi_pkt_buf_size0;
+ uint_t pkt_buf_size1;
+ uint_t pkt_buf_size1_bytes;
+ uint_t npi_pkt_buf_size1;
+ uint_t pkt_buf_size2;
+ uint_t pkt_buf_size2_bytes;
+ uint_t npi_pkt_buf_size2;
+
+ uint64_t rbr_head_pp;
+ uint64_t rbr_tail_pp;
+ uint32_t *rbr_desc_vp;
+
+ p_rx_rcr_ring_t rx_rcr_p;
+
+ rx_dma_ent_msk_t rx_dma_ent_mask;
+
+ rbr_hdh_t rbr_head;
+ rbr_hdl_t rbr_tail;
+ uint_t rbr_wr_index;
+ uint_t rbr_rd_index;
+ uint_t rbr_hw_head_index;
+ uint64_t rbr_hw_head_ptr;
+
+ /* may not be needed */
+ p_nxge_rbb_t rbb_p;
+
+ rxring_info_t *ring_info;
+#ifdef RX_USE_RECLAIM_POST
+ uint32_t hw_freed;
+ uint32_t sw_freed;
+ uint32_t msg_rd_index;
+ uint32_t msg_cnt;
+#endif
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ uint64_t hv_rx_buf_base_ioaddr_pp;
+ uint64_t hv_rx_buf_ioaddr_size;
+ uint64_t hv_rx_cntl_base_ioaddr_pp;
+ uint64_t hv_rx_cntl_ioaddr_size;
+ boolean_t hv_set;
+#endif
+ uint_t rbr_consumed;
+ uint_t rbr_threshold_hi;
+ uint_t rbr_threshold_lo;
+ nxge_rxbuf_type_t rbr_bufsize_type;
+ boolean_t rbr_use_bcopy;
+} rx_rbr_ring_t, *p_rx_rbr_ring_t;
+
+/* Receive Mailbox */
+typedef struct _rx_mbox_t {
+ nxge_os_dma_common_t rx_mbox;
+ rxdma_cfig1_t rx_cfg1;
+ rxdma_cfig2_t rx_cfg2;
+ uint64_t mbox_addr;
+ boolean_t cfg_set;
+
+ nxge_os_mutex_t lock;
+ uint16_t index;
+ struct _nxge_t *nxgep;
+ uint16_t rdc;
+} rx_mbox_t, *p_rx_mbox_t;
+
+
+typedef struct _rx_rbr_rings_t {
+ p_rx_rbr_ring_t *rbr_rings;
+ uint32_t ndmas;
+ boolean_t rxbuf_allocated;
+} rx_rbr_rings_t, *p_rx_rbr_rings_t;
+
+typedef struct _rx_rcr_rings_t {
+ p_rx_rcr_ring_t *rcr_rings;
+ uint32_t ndmas;
+ boolean_t cntl_buf_allocated;
+} rx_rcr_rings_t, *p_rx_rcr_rings_t;
+
+typedef struct _rx_mbox_areas_t {
+ p_rx_mbox_t *rxmbox_areas;
+ uint32_t ndmas;
+ boolean_t mbox_allocated;
+} rx_mbox_areas_t, *p_rx_mbox_areas_t;
+
+/*
+ * Global register definitions per chip and they are initialized
+ * using the function zero control registers.
+ * .
+ */
+
+typedef struct _rxdma_globals {
+ boolean_t mode32;
+ uint16_t rxdma_ck_div_cnt;
+ uint16_t rxdma_red_ran_init;
+ uint32_t rxdma_eing_timeout;
+} rxdma_globals_t, *p_rxdma_globals;
+
+
+/*
+ * Receive DMA Prototypes.
+ */
+nxge_status_t nxge_init_rxdma_channel_rcrflush(p_nxge_t, uint8_t);
+nxge_status_t nxge_init_rxdma_channels(p_nxge_t);
+void nxge_uninit_rxdma_channels(p_nxge_t);
+nxge_status_t nxge_reset_rxdma_channel(p_nxge_t, uint16_t);
+nxge_status_t nxge_init_rxdma_channel_cntl_stat(p_nxge_t,
+ uint16_t, p_rx_dma_ctl_stat_t);
+nxge_status_t nxge_enable_rxdma_channel(p_nxge_t,
+ uint16_t, p_rx_rbr_ring_t, p_rx_rcr_ring_t,
+ p_rx_mbox_t);
+nxge_status_t nxge_init_rxdma_channel_event_mask(p_nxge_t,
+ uint16_t, p_rx_dma_ent_msk_t);
+
+nxge_status_t nxge_rxdma_hw_mode(p_nxge_t, boolean_t);
+void nxge_hw_start_rx(p_nxge_t);
+void nxge_fixup_rxdma_rings(p_nxge_t);
+nxge_status_t nxge_dump_rxdma_channel(p_nxge_t, uint8_t);
+
+void nxge_rxdma_fix_channel(p_nxge_t, uint16_t);
+void nxge_rxdma_fixup_channel(p_nxge_t, uint16_t, int);
+int nxge_rxdma_get_ring_index(p_nxge_t, uint16_t);
+
+void nxge_rxdma_regs_dump_channels(p_nxge_t);
+nxge_status_t nxge_rxdma_handle_sys_errors(p_nxge_t);
+void nxge_rxdma_inject_err(p_nxge_t, uint32_t, uint8_t);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_RXDMA_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_rxdma_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_rxdma_hw.h
new file mode 100644
index 0000000000..8657de219b
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_rxdma_hw.h
@@ -0,0 +1,1899 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_RXDMA_HW_H
+#define _SYS_NXGE_NXGE_RXDMA_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+#include <nxge_hw.h>
+
+/*
+ * NIU: Receive DMA Channels
+ */
+/* Receive DMA Clock Divider */
+#define RX_DMA_CK_DIV_REG (FZC_DMC + 0x00000)
+#define RX_DMA_CK_DIV_SHIFT 0 /* bits 15:0 */
+#define RX_DMA_CK_DIV_MASK 0x000000000000FFFFULL
+
+typedef union _rx_dma_ck_div_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:16;
+ uint32_t cnt:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cnt:16;
+ uint32_t res1_1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_dma_ck_div_t, *p_rx_dma_ck_div_t;
+
+
+/*
+ * Default Port Receive DMA Channel (RDC)
+ */
+#define DEF_PT_RDC_REG(port) (FZC_DMC + 0x00008 * (port + 1))
+#define DEF_PT0_RDC_REG (FZC_DMC + 0x00008)
+#define DEF_PT1_RDC_REG (FZC_DMC + 0x00010)
+#define DEF_PT2_RDC_REG (FZC_DMC + 0x00018)
+#define DEF_PT3_RDC_REG (FZC_DMC + 0x00020)
+#define DEF_PT_RDC_SHIFT 0 /* bits 4:0 */
+#define DEF_PT_RDC_MASK 0x000000000000001FULL
+
+
+#define RDC_TBL_REG (FZC_ZCP + 0x10000)
+#define RDC_TBL_SHIFT 0 /* bits 4:0 */
+#define RDC_TBL_MASK 0x000000000000001FULL
+
+/* For the default port RDC and RDC table */
+typedef union _def_pt_rdc_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:27;
+ uint32_t rdc:5;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rdc:5;
+ uint32_t res1_1:27;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} def_pt_rdc_t, *p_def_pt_rdc_t;
+
+typedef union _rdc_tbl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:28;
+ uint32_t rdc:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rdc:4;
+ uint32_t res1_1:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdc_tbl_t, *p_rdc_tbl_t;
+
+/*
+ * RDC: 32 bit Addressing mode
+ */
+#define RX_ADDR_MD_REG (FZC_DMC + 0x00070)
+#define RX_ADDR_MD_SHIFT 0 /* bits 0:0 */
+#define RX_ADDR_MD_SET_32 0x0000000000000001ULL /* 1 to select 32 bit */
+#define RX_ADDR_MD_MASK 0x0000000000000001ULL
+
+typedef union _rx_addr_md_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:28;
+ uint32_t dbg_pt_mux_sel:2;
+ uint32_t ram_acc:1;
+ uint32_t mode32:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mode32:1;
+ uint32_t ram_acc:1;
+ uint32_t dbg_pt_mux_sel:2;
+ uint32_t res1_1:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_addr_md_t, *p_rx_addr_md_t;
+
+/*
+ * RDC: Port Scheduler
+ */
+
+#define PT_DRR_WT_REG(portnm) ((FZC_DMC + 0x00028) + (portnm * 8))
+#define PT_DRR_WT0_REG (FZC_DMC + 0x00028)
+#define PT_DRR_WT1_REG (FZC_DMC + 0x00030)
+#define PT_DRR_WT2_REG (FZC_DMC + 0x00038)
+#define PT_DRR_WT3_REG (FZC_DMC + 0x00040)
+#define PT_DRR_WT_SHIFT 0
+#define PT_DRR_WT_MASK 0x000000000000FFFFULL /* bits 15:0 */
+#define PT_DRR_WT_DEFAULT_10G 0x0400
+#define PT_DRR_WT_DEFAULT_1G 0x0066
+typedef union _pt_drr_wt_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:16;
+ uint32_t wt:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t wt:16;
+ uint32_t res1_1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pt_drr_wt_t, *p_pt_drr_wt_t;
+
+#define NXGE_RX_DRR_WT_10G 0x400
+#define NXGE_RX_DRR_WT_1G 0x066
+
+/* Port FIFO Usage */
+#define PT_USE_REG(portnum) ((FZC_DMC + 0x00048) + (portnum * 8))
+#define PT_USE0_REG (FZC_DMC + 0x00048)
+#define PT_USE1_REG (FZC_DMC + 0x00050)
+#define PT_USE2_REG (FZC_DMC + 0x00058)
+#define PT_USE3_REG (FZC_DMC + 0x00060)
+#define PT_USE_SHIFT 0 /* bits 19:0 */
+#define PT_USE_MASK 0x00000000000FFFFFULL
+
+typedef union _pt_use_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:12;
+ uint32_t cnt:20;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cnt:20;
+ uint32_t res1_1:12;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} pt_use_t, *p_pt_use_t;
+
+/*
+ * RDC: Partitioning Support
+ * (Each of the following registers is for each RDC)
+ * Please refer to nxge_hw.h for the common logical
+ * page configuration register definitions.
+ */
+#define RX_LOG_REG_SIZE 0x40
+#define RX_LOG_DMA_OFFSET(channel) (channel * RX_LOG_REG_SIZE)
+
+#define RX_LOG_PAGE_VLD_REG (FZC_DMC + 0x20000)
+#define RX_LOG_PAGE_MASK1_REG (FZC_DMC + 0x20008)
+#define RX_LOG_PAGE_VAL1_REG (FZC_DMC + 0x20010)
+#define RX_LOG_PAGE_MASK2_REG (FZC_DMC + 0x20018)
+#define RX_LOG_PAGE_VAL2_REG (FZC_DMC + 0x20020)
+#define RX_LOG_PAGE_RELO1_REG (FZC_DMC + 0x20028)
+#define RX_LOG_PAGE_RELO2_REG (FZC_DMC + 0x20030)
+#define RX_LOG_PAGE_HDL_REG (FZC_DMC + 0x20038)
+
+/* RX and TX have the same definitions */
+#define RX_LOG_PAGE1_VLD_SHIFT 1 /* bit 1 */
+#define RX_LOG_PAGE0_VLD_SHIFT 0 /* bit 0 */
+#define RX_LOG_PAGE1_VLD 0x0000000000000002ULL
+#define RX_LOG_PAGE0_VLD 0x0000000000000001ULL
+#define RX_LOG_PAGE1_VLD_MASK 0x0000000000000002ULL
+#define RX_LOG_PAGE0_VLD_MASK 0x0000000000000001ULL
+#define RX_LOG_FUNC_VLD_SHIFT 2 /* bit 3:2 */
+#define RX_LOG_FUNC_VLD_MASK 0x000000000000000CULL
+
+#define LOG_PAGE_ADDR_SHIFT 12 /* bits[43:12] --> bits[31:0] */
+
+/* RDC: Weighted Random Early Discard */
+#define RED_RAN_INIT_REG (FZC_DMC + 0x00068)
+
+#define RED_RAN_INIT_SHIFT 0 /* bits 15:0 */
+#define RED_RAN_INIT_MASK 0x000000000000ffffULL
+
+/* Weighted Random */
+typedef union _red_ran_init_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:15;
+ uint32_t enable:1;
+ uint32_t init:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t init:16;
+ uint32_t enable:1;
+ uint32_t res1_1:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} red_ran_init_t, *p_red_ran_init_t;
+
+/*
+ * Buffer block descriptor
+ */
+typedef struct _rx_desc_t {
+ uint32_t block_addr;
+} rx_desc_t, *p_rx_desc_t;
+
+/*
+ * RDC: RED Parameter
+ * (Each DMC has one RED register)
+ */
+#define RDC_RED_CHANNEL_SIZE (0x40)
+#define RDC_RED_CHANNEL_OFFSET(channel) (channel * RDC_RED_CHANNEL_SIZE)
+
+#define RDC_RED_PARA_REG (FZC_DMC + 0x30000)
+#define RDC_RED_RDC_PARA_REG(rdc) \
+ (RDC_RED_PARA_REG + (rdc * RDC_RED_CHANNEL_SIZE))
+
+/* the layout of this register is rx_disc_cnt_t */
+#define RDC_RED_DISC_CNT_REG (FZC_DMC + 0x30008)
+#define RDC_RED_RDC_DISC_REG(rdc) \
+ (RDC_RED_DISC_CNT_REG + (rdc * RDC_RED_CHANNEL_SIZE))
+
+
+#define RDC_RED_PARA1_RBR_SCL_SHIFT 0 /* bits 2:0 */
+#define RDC_RED_PARA1_RBR_SCL_MASK 0x0000000000000007ULL
+#define RDC_RED_PARA1_ENB_SHIFT 3 /* bit 3 */
+#define RDC_RED_PARA1_ENB 0x0000000000000008ULL
+#define RDC_RED_PARA1_ENB_MASK 0x0000000000000008ULL
+
+#define RDC_RED_PARA_WIN_SHIFT 0 /* bits 3:0 */
+#define RDC_RED_PARA_WIN_MASK 0x000000000000000fULL
+#define RDC_RED_PARA_THRE_SHIFT 4 /* bits 15:4 */
+#define RDC_RED_PARA_THRE_MASK 0x00000000000000f0ULL
+#define RDC_RED_PARA_WIN_SYN_SHIFT 16 /* bits 19:16 */
+#define RDC_RED_PARA_WIN_SYN_MASK 0x00000000000000f0ULL
+#define RDC_RED_PARA_THRE_SYN_SHIFT 20 /* bits 31:20 */
+#define RDC_RED_PARA_THRE_SYN_MASK 0x00000000000fff00ULL
+
+/* RDC: RED parameters */
+typedef union _rdc_red_para_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t thre_sync:12;
+ uint32_t win_syn:4;
+ uint32_t thre:12;
+ uint32_t win:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t win:4;
+ uint32_t thre:12;
+ uint32_t win_syn:4;
+ uint32_t thre_sync:12;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdc_red_para_t, *p_rdc_red_para_t;
+
+/*
+ * RDC: Receive DMA Datapath Configuration
+ * The following register definitions are for
+ * each DMA channel. Each DMA CSR is 512 bytes
+ * (0x200).
+ */
+#define RXDMA_CFIG1_REG (DMC + 0x00000)
+#define RXDMA_CFIG2_REG (DMC + 0x00008)
+
+#define RXDMA_CFIG1_MBADDR_H_SHIFT 0 /* bits 11:0 */
+#define RXDMA_CFIG1_MBADDR_H_MASK 0x0000000000000fc0ULL
+#define RXDMA_CFIG1_RST_SHIFT 30 /* bit 30 */
+#define RXDMA_CFIG1_RST 0x0000000040000000ULL
+#define RXDMA_CFIG1_RST_MASK 0x0000000040000000ULL
+#define RXDMA_CFIG1_EN_SHIFT 31
+#define RXDMA_CFIG1_EN 0x0000000080000000ULL
+#define RXDMA_CFIG1_EN_MASK 0x0000000080000000ULL
+
+typedef union _rxdma_cfig1_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t en:1;
+ uint32_t rst:1;
+ uint32_t qst:1;
+ uint32_t res2:17;
+ uint32_t mbaddr_h:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mbaddr_h:12;
+ uint32_t res2:17;
+ uint32_t qst:1;
+ uint32_t rst:1;
+ uint32_t en:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rxdma_cfig1_t, *p_rxdma_cfig1_t;
+
+#define RXDMA_HDR_SIZE_DEFAULT 2
+#define RXDMA_HDR_SIZE_FULL 18
+
+#define RXDMA_CFIG2_FULL_HDR_SHIFT 0 /* Set to 1 */
+#define RXDMA_CFIG2_FULL_HDR 0x0000000000000001ULL
+#define RXDMA_CFIG2_FULL_HDR_MASK 0x0000000000000001ULL
+#define RXDMA_CFIG2_OFFSET_SHIFT 1 /* bit 3:1 */
+#define RXDMA_CFIG2_OFFSET_MASK 0x000000004000000eULL
+#define RXDMA_CFIG2_MBADDR_L_SHIFT 6 /* bit 31:6 */
+#define RXDMA_CFIG2_MBADDR_L_MASK 0x00000000ffffffc0ULL
+
+typedef union _rxdma_cfig2_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t mbaddr:26;
+ uint32_t res2:3;
+ uint32_t offset:2;
+ uint32_t full_hdr:1;
+
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t full_hdr:1;
+ uint32_t offset:2;
+ uint32_t res2:3;
+ uint32_t mbaddr:26;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rxdma_cfig2_t, *p_rxdma_cfig2_t;
+
+/*
+ * RDC: Receive Block Ring Configuration
+ * The following register definitions are for
+ * each DMA channel.
+ */
+#define RBR_CFIG_A_REG (DMC + 0x00010)
+#define RBR_CFIG_B_REG (DMC + 0x00018)
+#define RBR_KICK_REG (DMC + 0x00020)
+#define RBR_STAT_REG (DMC + 0x00028)
+#define RBR_HDH_REG (DMC + 0x00030)
+#define RBR_HDL_REG (DMC + 0x00038)
+
+#define RBR_CFIG_A_STADDR_SHIFT 6 /* bits 17:6 */
+#define RBR_CFIG_A_STDADDR_MASK 0x000000000003ffc0ULL
+#define RBR_CFIG_A_STADDR_BASE_SHIFT 18 /* bits 43:18 */
+#define RBR_CFIG_A_STDADDR_BASE_MASK 0x00000ffffffc0000ULL
+#define RBR_CFIG_A_LEN_SHIFT 48 /* bits 63:48 */
+#define RBR_CFIG_A_LEN_MASK 0xFFFF000000000000ULL
+
+typedef union _rbr_cfig_a_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t len:16;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:16;
+#endif
+ } hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t staddr_base:14;
+ uint32_t staddr:12;
+ uint32_t res2:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:6;
+ uint32_t staddr:12;
+ uint32_t staddr_base:14;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t len:16;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:16;
+#endif
+ } hdw;
+#endif
+ } bits;
+} rbr_cfig_a_t, *p_rbr_cfig_a_t;
+
+
+#define RBR_CFIG_B_BUFSZ0_SHIFT 0 /* bit 1:0 */
+#define RBR_CFIG_B_BUFSZ0_MASK 0x0000000000000001ULL
+#define RBR_CFIG_B_VLD0_SHIFT 7 /* bit 7 */
+#define RBR_CFIG_B_VLD0 0x0000000000000008ULL
+#define RBR_CFIG_B_VLD0_MASK 0x0000000000000008ULL
+#define RBR_CFIG_B_BUFSZ1_SHIFT 8 /* bit 9:8 */
+#define RBR_CFIG_B_BUFSZ1_MASK 0x0000000000000300ULL
+#define RBR_CFIG_B_VLD1_SHIFT 15 /* bit 15 */
+#define RBR_CFIG_B_VLD1 0x0000000000008000ULL
+#define RBR_CFIG_B_VLD1_MASK 0x0000000000008000ULL
+#define RBR_CFIG_B_BUFSZ2_SHIFT 16 /* bit 17:16 */
+#define RBR_CFIG_B_BUFSZ2_MASK 0x0000000000030000ULL
+#define RBR_CFIG_B_VLD2_SHIFT 23 /* bit 23 */
+#define RBR_CFIG_B_VLD2 0x0000000000800000ULL
+#define RBR_CFIG_B_BKSIZE_SHIFT 24 /* bit 25:24 */
+#define RBR_CFIG_B_BKSIZE_MASK 0x0000000003000000ULL
+
+
+typedef union _rbr_cfig_b_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:6;
+ uint32_t bksize:2;
+ uint32_t vld2:1;
+ uint32_t res2:5;
+ uint32_t bufsz2:2;
+ uint32_t vld1:1;
+ uint32_t res3:5;
+ uint32_t bufsz1:2;
+ uint32_t vld0:1;
+ uint32_t res4:5;
+ uint32_t bufsz0:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t bufsz0:2;
+ uint32_t res4:5;
+ uint32_t vld0:1;
+ uint32_t bufsz1:2;
+ uint32_t res3:5;
+ uint32_t vld1:1;
+ uint32_t bufsz2:2;
+ uint32_t res2:5;
+ uint32_t vld2:1;
+ uint32_t bksize:2;
+ uint32_t res1_1:6;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rbr_cfig_b_t, *p_rbr_cfig_b_t;
+
+
+#define RBR_KICK_SHIFT 0 /* bit 15:0 */
+#define RBR_KICK_MASK 0x00000000000ffff1ULL
+
+
+typedef union _rbr_kick_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:16;
+ uint32_t bkadd:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t bkadd:16;
+ uint32_t res1_1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rbr_kick_t, *p_rbr_kick_t;
+
+#define RBR_STAT_QLEN_SHIFT 0 /* bit bit 15:0 */
+#define RBR_STAT_QLEN_MASK 0x000000000000ffffULL
+#define RBR_STAT_OFLOW_SHIFT 16 /* bit 16 */
+#define RBR_STAT_OFLOW 0x0000000000010000ULL
+#define RBR_STAT_OFLOW_MASK 0x0000000000010000ULL
+
+typedef union _rbr_stat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:15;
+ uint32_t oflow:1;
+ uint32_t qlen:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t qlen:16;
+ uint32_t oflow:1;
+ uint32_t res1_1:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rbr_stat_t, *p_rbr_stat_t;
+
+
+#define RBR_HDH_HEAD_H_SHIFT 0 /* bit 11:0 */
+#define RBR_HDH_HEAD_H_MASK 0x0000000000000fffULL
+typedef union _rbr_hdh_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:20;
+ uint32_t head_h:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t head_h:12;
+ uint32_t res1_1:20;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rbr_hdh_t, *p_rbr_hdh_t;
+
+#define RBR_HDL_HEAD_L_SHIFT 2 /* bit 31:2 */
+#define RBR_HDL_HEAD_L_MASK 0x00000000FFFFFFFCULL
+
+typedef union _rbr_hdl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t head_l:30;
+ uint32_t res2:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:2;
+ uint32_t head_l:30;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rbr_hdl_t, *p_rbr_hdl_t;
+
+/*
+ * Receive Completion Ring (RCR)
+ */
+#define RCR_PKT_BUF_ADDR_SHIFT 0 /* bit 37:0 */
+#define RCR_PKT_BUF_ADDR_SHIFT_FULL 6 /* fulll buffer address */
+#define RCR_PKT_BUF_ADDR_MASK 0x0000003FFFFFFFFFULL
+#define RCR_PKTBUFSZ_SHIFT 38 /* bit 39:38 */
+#define RCR_PKTBUFSZ_MASK 0x000000C000000000ULL
+#define RCR_L2_LEN_SHIFT 40 /* bit 39:38 */
+#define RCR_L2_LEN_MASK 0x003fff0000000000ULL
+#define RCR_DCF_ERROR_SHIFT 54 /* bit 54 */
+#define RCR_DCF_ERROR_MASK 0x0040000000000000ULL
+#define RCR_ERROR_SHIFT 55 /* bit 57:55 */
+#define RCR_ERROR_MASK 0x0380000000000000ULL
+#define RCR_PROMIS_SHIFT 58 /* bit 58 */
+#define RCR_PROMIS_MASK 0x0400000000000000ULL
+#define RCR_FRAG_SHIFT 59 /* bit 59 */
+#define RCR_FRAG_MASK 0x0800000000000000ULL
+#define RCR_ZERO_COPY_SHIFT 60 /* bit 60 */
+#define RCR_ZERO_COPY_MASK 0x1000000000000000ULL
+#define RCR_PKT_TYPE_SHIFT 61 /* bit 62:61 */
+#define RCR_PKT_TYPE_MASK 0x6000000000000000ULL
+#define RCR_MULTI_SHIFT 63 /* bit 63 */
+#define RCR_MULTI_MASK 0x8000000000000000ULL
+
+#define RCR_PKTBUFSZ_0 0x00
+#define RCR_PKTBUFSZ_1 0x01
+#define RCR_PKTBUFSZ_2 0x02
+#define RCR_SINGLE_BLOCK 0x03
+
+#define RCR_NO_ERROR 0x0
+#define RCR_L2_ERROR 0x1
+#define RCR_L4_CSUM_ERROR 0x3
+#define RCR_FFLP_SOFT_ERROR 0x4
+#define RCR_ZCP_SOFT_ERROR 0x5
+#define RCR_ERROR_RESERVE 0x6
+#define RCR_ERROR_RESERVE_END 0x7
+
+#define RCR_PKT_TYPE_UDP 0x1
+#define RCR_PKT_TYPE_TCP 0x2
+#define RCR_PKT_TYPE_SCTP 0x3
+#define RCR_PKT_TYPE_OTHERS 0x0
+#define RCR_PKT_IS_TCP 0x2000000000000000ULL
+#define RCR_PKT_IS_UDP 0x4000000000000000ULL
+#define RCR_PKT_IS_SCTP 0x6000000000000000ULL
+
+
+typedef union _rcr_entry_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t multi:1;
+ uint32_t pkt_type:2;
+ uint32_t zero_copy:1;
+ uint32_t noport:1;
+ uint32_t promis:1;
+ uint32_t error:3;
+ uint32_t dcf_err:1;
+ uint32_t l2_len:14;
+ uint32_t pktbufsz:2;
+ uint32_t pkt_buf_addr:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_buf_addr:6;
+ uint32_t pktbufsz:2;
+ uint32_t l2_len:14;
+ uint32_t dcf_err:1;
+ uint32_t error:3;
+ uint32_t promis:1;
+ uint32_t noport:1;
+ uint32_t zero_copy:1;
+ uint32_t pkt_type:2;
+ uint32_t multi:1;
+#endif
+ } hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pkt_buf_addr:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_buf_addr:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t multi:1;
+ uint32_t pkt_type:2;
+ uint32_t zero_copy:1;
+ uint32_t noport:1;
+ uint32_t promis:1;
+ uint32_t error:3;
+ uint32_t dcf_err:1;
+ uint32_t l2_len:14;
+ uint32_t pktbufsz:2;
+ uint32_t pkt_buf_addr:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_buf_addr:6;
+ uint32_t pktbufsz:2;
+ uint32_t l2_len:14;
+ uint32_t dcf_err:1;
+ uint32_t error:3;
+ uint32_t promis:1;
+ uint32_t noport:1;
+ uint32_t zero_copy:1;
+ uint32_t pkt_type:2;
+ uint32_t multi:1;
+#endif
+ } hdw;
+#endif
+ } bits;
+} rcr_entry_t, *p_rcr_entry_t;
+
+/*
+ * Receive Completion Ring Configuration.
+ * (for each DMA channel)
+ */
+#define RCRCFIG_A_REG (DMC + 0x00040)
+#define RCRCFIG_B_REG (DMC + 0x00048)
+#define RCRSTAT_A_REG (DMC + 0x00050)
+#define RCRSTAT_B_REG (DMC + 0x00058)
+#define RCRSTAT_C_REG (DMC + 0x00060)
+#define RX_DMA_ENT_MSK_REG (DMC + 0x00068)
+#define RX_DMA_CTL_STAT_REG (DMC + 0x00070)
+#define RCR_FLSH_REG (DMC + 0x00078)
+#if OLD
+#define RX_DMA_LOGA_REG (DMC + 0x00080)
+#define RX_DMA_LOGB_REG (DMC + 0x00088)
+#endif
+#define RX_DMA_CTL_STAT_DBG_REG (DMC + 0x00098)
+
+/* (DMC + 0x00050) */
+#define RCRCFIG_A_STADDR_SHIFT 6 /* bit 18:6 */
+#define RCRCFIG_A_STADDR_MASK 0x000000000007FFC0ULL
+#define RCRCFIG_A_STADDR_BASE_SHIF 19 /* bit 43:19 */
+#define RCRCFIG_A_STADDR_BASE_MASK 0x00000FFFFFF80000ULL
+#define RCRCFIG_A_LEN_SHIF 48 /* bit 63:48 */
+#define RCRCFIG_A_LEN__MASK 0xFFFF000000000000ULL
+
+/* (DMC + 0x00058) */
+#define RCRCFIG_B_TIMEOUT_SHIFT 0 /* bit 5:0 */
+#define RCRCFIG_B_TIMEOUT_MASK 0x000000000000003FULL
+#define RCRCFIG_B_ENTOUT_SHIFT 15 /* bit 15 */
+#define RCRCFIG_B_TIMEOUT 0x0000000000008000ULL
+#define RCRCFIG_B_PTHRES_SHIFT 16 /* bit 31:16 */
+#define RCRCFIG_B_PTHRES_MASK 0x00000000FFFF0000ULL
+
+/* (DMC + 0x00060) */
+#define RCRSTAT_A_QLEN_SHIFT 0 /* bit 15:0 */
+#define RCRSTAT_A_QLEN_MASK 0x000000000000FFFFULL
+#define RCRSTAT_A_PKT_OFL_SHIFT 16 /* bit 16 */
+#define RCRSTAT_A_PKT_OFL_MASK 0x0000000000010000ULL
+#define RCRSTAT_A_ENT_OFL_SHIFT 17 /* bit 17 */
+#define RCRSTAT_A_ENT_QFL_MASK 0x0000000000020000ULL
+
+#define RCRSTAT_C_TLPTR_H_SHIFT 0 /* bit 11:0 */
+#define RCRSTAT_C_TLPTR_H_MASK 0x0000000000000FFFULL
+
+#define RCRSTAT_D_TLPTR_L_SHIFT 3 /* bit 31:3 */
+#define RCRSTAT_D_TLPTR_L_MASK 0x00000000FFFFFFF8ULL
+
+/* Receive DMA Interrupt Behavior: Event Mask (DMC + 0x00068) */
+#define RX_DMA_ENT_MSK_CFIGLOGPGE_SHIFT 0 /* bit 0: 0 to flag */
+#define RX_DMA_ENT_MSK_CFIGLOGPGE_MASK 0x0000000000000001ULL
+#define RX_DMA_ENT_MSK_RBRLOGPGE_SHIFT 1 /* bit 1: 0 to flag */
+#define RX_DMA_ENT_MSK_RBRLOGPGE_MASK 0x0000000000000002ULL
+#define RX_DMA_ENT_MSK_RBRFULL_SHIFT 2 /* bit 2: 0 to flag */
+#define RX_DMA_ENT_MSK_RBRFULL_MASK 0x0000000000000004ULL
+#define RX_DMA_ENT_MSK_RBREMPTY_SHIFT 3 /* bit 3: 0 to flag */
+#define RX_DMA_ENT_MSK_RBREMPTY_MASK 0x0000000000000008ULL
+#define RX_DMA_ENT_MSK_RCRFULL_SHIFT 4 /* bit 4: 0 to flag */
+#define RX_DMA_ENT_MSK_RCRFULL_MASK 0x0000000000000010ULL
+#define RX_DMA_ENT_MSK_RCRINCON_SHIFT 5 /* bit 5: 0 to flag */
+#define RX_DMA_ENT_MSK_RCRINCON_MASK 0x0000000000000020ULL
+#define RX_DMA_ENT_MSK_CONFIG_ERR_SHIFT 6 /* bit 6: 0 to flag */
+#define RX_DMA_ENT_MSK_CONFIG_ERR_MASK 0x0000000000000040ULL
+#define RX_DMA_ENT_MSK_RCRSH_FULL_SHIFT 7 /* bit 7: 0 to flag */
+#define RX_DMA_ENT_MSK_RCRSH_FULL_MASK 0x0000000000000080ULL
+#define RX_DMA_ENT_MSK_RBR_PRE_EMPTY_SHIFT 8 /* bit 8: 0 to flag */
+#define RX_DMA_ENT_MSK_RBR_PRE_EMPTY_MASK 0x0000000000000100ULL
+#define RX_DMA_ENT_MSK_WRED_DROP_SHIFT 9 /* bit 9: 0 to flag */
+#define RX_DMA_ENT_MSK_WRED_DROP_MASK 0x0000000000000200ULL
+#define RX_DMA_ENT_MSK_PTDROP_PKT_SHIFT 10 /* bit 10: 0 to flag */
+#define RX_DMA_ENT_MSK_PTDROP_PKT_MASK 0x0000000000000400ULL
+#define RX_DMA_ENT_MSK_RBR_PRE_PAR_SHIFT 11 /* bit 11: 0 to flag */
+#define RX_DMA_ENT_MSK_RBR_PRE_PAR_MASK 0x0000000000000800ULL
+#define RX_DMA_ENT_MSK_RCR_SHA_PAR_SHIFT 12 /* bit 12: 0 to flag */
+#define RX_DMA_ENT_MSK_RCR_SHA_PAR_MASK 0x0000000000001000ULL
+#define RX_DMA_ENT_MSK_RCRTO_SHIFT 13 /* bit 13: 0 to flag */
+#define RX_DMA_ENT_MSK_RCRTO_MASK 0x0000000000002000ULL
+#define RX_DMA_ENT_MSK_THRES_SHIFT 14 /* bit 14: 0 to flag */
+#define RX_DMA_ENT_MSK_THRES_MASK 0x0000000000004000ULL
+#define RX_DMA_ENT_MSK_DC_FIFO_ERR_SHIFT 16 /* bit 16: 0 to flag */
+#define RX_DMA_ENT_MSK_DC_FIFO_ERR_MASK 0x0000000000010000ULL
+#define RX_DMA_ENT_MSK_RCR_ACK_ERR_SHIFT 17 /* bit 17: 0 to flag */
+#define RX_DMA_ENT_MSK_RCR_ACK_ERR_MASK 0x0000000000020000ULL
+#define RX_DMA_ENT_MSK_RSP_DAT_ERR_SHIFT 18 /* bit 18: 0 to flag */
+#define RX_DMA_ENT_MSK_RSP_DAT_ERR_MASK 0x0000000000040000ULL
+#define RX_DMA_ENT_MSK_BYTE_EN_BUS_SHIFT 19 /* bit 19: 0 to flag */
+#define RX_DMA_ENT_MSK_BYTE_EN_BUS_MASK 0x0000000000080000ULL
+#define RX_DMA_ENT_MSK_RSP_CNT_ERR_SHIFT 20 /* bit 20: 0 to flag */
+#define RX_DMA_ENT_MSK_RSP_CNT_ERR_MASK 0x0000000000100000ULL
+#define RX_DMA_ENT_MSK_RBR_TMOUT_SHIFT 21 /* bit 21: 0 to flag */
+#define RX_DMA_ENT_MSK_RBR_TMOUT_MASK 0x0000000000200000ULL
+#define RX_DMA_ENT_MSK_ALL (RX_DMA_ENT_MSK_CFIGLOGPGE_MASK | \
+ RX_DMA_ENT_MSK_RBRLOGPGE_MASK | \
+ RX_DMA_ENT_MSK_RBRFULL_MASK | \
+ RX_DMA_ENT_MSK_RBREMPTY_MASK | \
+ RX_DMA_ENT_MSK_RCRFULL_MASK | \
+ RX_DMA_ENT_MSK_RCRINCON_MASK | \
+ RX_DMA_ENT_MSK_CONFIG_ERR_MASK | \
+ RX_DMA_ENT_MSK_RCRSH_FULL_MASK | \
+ RX_DMA_ENT_MSK_RBR_PRE_EMPTY_MASK | \
+ RX_DMA_ENT_MSK_WRED_DROP_MASK | \
+ RX_DMA_ENT_MSK_PTDROP_PKT_MASK | \
+ RX_DMA_ENT_MSK_PTDROP_PKT_MASK | \
+ RX_DMA_ENT_MSK_RBR_PRE_PAR_MASK | \
+ RX_DMA_ENT_MSK_RCR_SHA_PAR_MASK | \
+ RX_DMA_ENT_MSK_RCRTO_MASK | \
+ RX_DMA_ENT_MSK_THRES_MASK | \
+ RX_DMA_ENT_MSK_DC_FIFO_ERR_MASK | \
+ RX_DMA_ENT_MSK_RCR_ACK_ERR_MASK | \
+ RX_DMA_ENT_MSK_RSP_DAT_ERR_MASK | \
+ RX_DMA_ENT_MSK_BYTE_EN_BUS_MASK | \
+ RX_DMA_ENT_MSK_RSP_CNT_ERR_MASK | \
+ RX_DMA_ENT_MSK_RBR_TMOUT_MASK)
+
+/* Receive DMA Control and Status (DMC + 0x00070) */
+#define RX_DMA_CTL_STAT_PKTREAD_SHIFT 0 /* WO, bit 15:0 */
+#define RX_DMA_CTL_STAT_PKTREAD_MASK 0x000000000000ffffULL
+#define RX_DMA_CTL_STAT_PTRREAD_SHIFT 16 /* WO, bit 31:16 */
+#define RX_DMA_CTL_STAT_PTRREAD_MASK 0x00000000FFFF0000ULL
+#define RX_DMA_CTL_STAT_CFIGLOGPG_SHIFT 32 /* RO, bit 32 */
+#define RX_DMA_CTL_STAT_CFIGLOGPG 0x0000000100000000ULL
+#define RX_DMA_CTL_STAT_CFIGLOGPG_MASK 0x0000000100000000ULL
+#define RX_DMA_CTL_STAT_RBRLOGPG_SHIFT 33 /* RO, bit 33 */
+#define RX_DMA_CTL_STAT_RBRLOGPG 0x0000000200000000ULL
+#define RX_DMA_CTL_STAT_RBRLOGPG_MASK 0x0000000200000000ULL
+#define RX_DMA_CTL_STAT_RBRFULL_SHIFT 34 /* RO, bit 34 */
+#define RX_DMA_CTL_STAT_RBRFULL 0x0000000400000000ULL
+#define RX_DMA_CTL_STAT_RBRFULL_MASK 0x0000000400000000ULL
+#define RX_DMA_CTL_STAT_RBREMPTY_SHIFT 35 /* RW1C, bit 35 */
+#define RX_DMA_CTL_STAT_RBREMPTY 0x0000000800000000ULL
+#define RX_DMA_CTL_STAT_RBREMPTY_MASK 0x0000000800000000ULL
+#define RX_DMA_CTL_STAT_RCRFULL_SHIFT 36 /* RW1C, bit 36 */
+#define RX_DMA_CTL_STAT_RCRFULL 0x0000001000000000ULL
+#define RX_DMA_CTL_STAT_RCRFULL_MASK 0x0000001000000000ULL
+#define RX_DMA_CTL_STAT_RCRINCON_SHIFT 37 /* RO, bit 37 */
+#define RX_DMA_CTL_STAT_RCRINCON 0x0000002000000000ULL
+#define RX_DMA_CTL_STAT_RCRINCON_MASK 0x0000002000000000ULL
+#define RX_DMA_CTL_STAT_CONFIG_ERR_SHIFT 38 /* RO, bit 38 */
+#define RX_DMA_CTL_STAT_CONFIG_ERR 0x0000004000000000ULL
+#define RX_DMA_CTL_STAT_CONFIG_ERR_MASK 0x0000004000000000ULL
+#define RX_DMA_CTL_STAT_RCR_SHDW_FULL_SHIFT 39 /* RO, bit 39 */
+#define RX_DMA_CTL_STAT_RCR_SHDW_FULL 0x0000008000000000ULL
+#define RX_DMA_CTL_STAT_RCR_SHDW_FULL_MASK 0x0000008000000000ULL
+#define RX_DMA_CTL_STAT_RBR_PRE_EMTY_MASK 0x0000010000000000ULL
+#define RX_DMA_CTL_STAT_RBR_PRE_EMTY_SHIFT 40 /* RO, bit 40 */
+#define RX_DMA_CTL_STAT_RBR_PRE_EMTY 0x0000010000000000ULL
+#define RX_DMA_CTL_STAT_RBR_PRE_EMTY_MASK 0x0000010000000000ULL
+#define RX_DMA_CTL_STAT_WRED_DROP_SHIFT 41 /* RO, bit 41 */
+#define RX_DMA_CTL_STAT_WRED_DROP 0x0000020000000000ULL
+#define RX_DMA_CTL_STAT_WRED_DROP_MASK 0x0000020000000000ULL
+#define RX_DMA_CTL_STAT_PORT_DROP_PKT_SHIFT 42 /* RO, bit 42 */
+#define RX_DMA_CTL_STAT_PORT_DROP_PKT 0x0000040000000000ULL
+#define RX_DMA_CTL_STAT_PORT_DROP_PKT_MASK 0x0000040000000000ULL
+#define RX_DMA_CTL_STAT_RBR_PRE_PAR_SHIFT 43 /* RO, bit 43 */
+#define RX_DMA_CTL_STAT_RBR_PRE_PAR 0x0000080000000000ULL
+#define RX_DMA_CTL_STAT_RBR_PRE_PAR_MASK 0x0000080000000000ULL
+#define RX_DMA_CTL_STAT_RCR_SHA_PAR_SHIFT 44 /* RO, bit 44 */
+#define RX_DMA_CTL_STAT_RCR_SHA_PAR 0x0000100000000000ULL
+#define RX_DMA_CTL_STAT_RCR_SHA_PAR_MASK 0x0000100000000000ULL
+#define RX_DMA_CTL_STAT_RCRTO_SHIFT 45 /* RW1C, bit 45 */
+#define RX_DMA_CTL_STAT_RCRTO 0x0000200000000000ULL
+#define RX_DMA_CTL_STAT_RCRTO_MASK 0x0000200000000000ULL
+#define RX_DMA_CTL_STAT_RCRTHRES_SHIFT 46 /* RO, bit 46 */
+#define RX_DMA_CTL_STAT_RCRTHRES 0x0000400000000000ULL
+#define RX_DMA_CTL_STAT_RCRTHRES_MASK 0x0000400000000000ULL
+#define RX_DMA_CTL_STAT_MEX_SHIFT 47 /* RW, bit 47 */
+#define RX_DMA_CTL_STAT_MEX 0x0000800000000000ULL
+#define RX_DMA_CTL_STAT_MEX_MASK 0x0000800000000000ULL
+#define RX_DMA_CTL_STAT_DC_FIFO_ERR_SHIFT 48 /* RW1C, bit 48 */
+#define RX_DMA_CTL_STAT_DC_FIFO_ERR 0x0001000000000000ULL
+#define RX_DMA_CTL_STAT_DC_FIFO_ERR_MASK 0x0001000000000000ULL
+#define RX_DMA_CTL_STAT_RCR_ACK_ERR_SHIFT 49 /* RO, bit 49 */
+#define RX_DMA_CTL_STAT_RCR_ACK_ERR 0x0002000000000000ULL
+#define RX_DMA_CTL_STAT_RCR_ACK_ERR_MASK 0x0002000000000000ULL
+#define RX_DMA_CTL_STAT_RSP_DAT_ERR_SHIFT 50 /* RO, bit 50 */
+#define RX_DMA_CTL_STAT_RSP_DAT_ERR 0x0004000000000000ULL
+#define RX_DMA_CTL_STAT_RSP_DAT_ERR_MASK 0x0004000000000000ULL
+
+#define RX_DMA_CTL_STAT_BYTE_EN_BUS_SHIFT 51 /* RO, bit 51 */
+#define RX_DMA_CTL_STAT_BYTE_EN_BUS 0x0008000000000000ULL
+#define RX_DMA_CTL_STAT_BYTE_EN_BUS_MASK 0x0008000000000000ULL
+
+#define RX_DMA_CTL_STAT_RSP_CNT_ERR_SHIFT 52 /* RO, bit 52 */
+#define RX_DMA_CTL_STAT_RSP_CNT_ERR 0x0010000000000000ULL
+#define RX_DMA_CTL_STAT_RSP_CNT_ERR_MASK 0x0010000000000000ULL
+
+#define RX_DMA_CTL_STAT_RBR_TMOUT_SHIFT 53 /* RO, bit 53 */
+#define RX_DMA_CTL_STAT_RBR_TMOUT 0x0020000000000000ULL
+#define RX_DMA_CTL_STAT_RBR_TMOUT_MASK 0x0020000000000000ULL
+#define RX_DMA_CTRL_STAT_ENT_MASK_SHIFT 32
+#define RX_DMA_CTL_STAT_ERROR (RX_DMA_ENT_MSK_ALL << \
+ RX_DMA_CTRL_STAT_ENT_MASK_SHIFT)
+
+/* the following are write 1 to clear bits */
+#define RX_DMA_CTL_STAT_WR1C RX_DMA_CTL_STAT_RBREMPTY | \
+ RX_DMA_CTL_STAT_RCR_SHDW_FULL | \
+ RX_DMA_CTL_STAT_RBR_PRE_EMTY | \
+ RX_DMA_CTL_STAT_WRED_DROP | \
+ RX_DMA_CTL_STAT_PORT_DROP_PKT | \
+ RX_DMA_CTL_STAT_RCRTO | \
+ RX_DMA_CTL_STAT_RCRTHRES | \
+ RX_DMA_CTL_STAT_DC_FIFO_ERR
+
+/* Receive DMA Interrupt Behavior: Force an update to RCR (DMC + 0x00078 */
+#define RCR_FLSH_SHIFT 0 /* RW, bit 0:0 */
+#define RCR_FLSH_SET 0x0000000000000001ULL
+#define RCR_FLSH_MASK 0x0000000000000001ULL
+
+/* Receive DMA Interrupt Behavior: the first error log (DMC + 0x00080 */
+#define RX_DMA_LOGA_ADDR_SHIFT 0 /* RO, bit 11:0 */
+#define RX_DMA_LOGA_ADDR 0x0000000000000FFFULL
+#define RX_DMA_LOGA_ADDR_MASK 0x0000000000000FFFULL
+#define RX_DMA_LOGA_TYPE_SHIFT 28 /* RO, bit 30:28 */
+#define RX_DMA_LOGA_TYPE 0x0000000070000000ULL
+#define RX_DMA_LOGA_TYPE_MASK 0x0000000070000FFFULL
+#define RX_DMA_LOGA_MULTI_SHIFT 28 /* RO, bit 30:28 */
+#define RX_DMA_LOGA_MULTI 0x0000000080000000ULL
+#define RX_DMA_LOGA_MULTI_MASK 0x0000000080000FFFULL
+
+/* Receive DMA Interrupt Behavior: the first error log (DMC + 0x00088 */
+#define RX_DMA_LOGA_ADDR_L_SHIFT 0 /* RO, bit 31:0 */
+#define RX_DMA_LOGA_ADDRL_L 0x00000000FFFFFFFFULL
+#define RX_DMA_LOGA_ADDR_LMASK 0x00000000FFFFFFFFULL
+
+typedef union _rcrcfig_a_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t len:16;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:16;
+#endif
+ } hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t staddr_base:13;
+ uint32_t staddr:13;
+ uint32_t res2:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:6;
+ uint32_t staddr:13;
+ uint32_t staddr_base:13;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t len:16;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:16;
+#endif
+ } hdw;
+#endif
+ } bits;
+} rcrcfig_a_t, *p_rcrcfig_a_t;
+
+
+typedef union _rcrcfig_b_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pthres:16;
+ uint32_t entout:1;
+ uint32_t res1:9;
+ uint32_t timeout:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t timeout:6;
+ uint32_t res1:9;
+ uint32_t entout:1;
+ uint32_t pthres:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rcrcfig_b_t, *p_rcrcfig_b_t;
+
+
+typedef union _rcrstat_a_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:16;
+ uint32_t qlen:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t qlen:16;
+ uint32_t res1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rcrstat_a_t, *p_rcrstat_a_t;
+
+
+typedef union _rcrstat_b_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:20;
+ uint32_t tlptr_h:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t tlptr_h:12;
+ uint32_t res1:20;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rcrstat_b_t, *p_rcrstat_b_t;
+
+
+typedef union _rcrstat_c_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t tlptr_l:29;
+ uint32_t res1:3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res1:3;
+ uint32_t tlptr_l:29;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rcrstat_c_t, *p_rcrstat_c_t;
+
+
+/* Receive DMA Event Mask */
+typedef union _rx_dma_ent_msk_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd2:10;
+ uint32_t rbr_tmout:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t rsrvd:1;
+ uint32_t rcrthres:1;
+ uint32_t rcrto:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t wred_drop:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t config_err:1;
+ uint32_t rcrincon:1;
+ uint32_t rcrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rbrfull:1;
+ uint32_t rbrlogpage:1;
+ uint32_t cfiglogpage:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cfiglogpage:1;
+ uint32_t rbrlogpage:1;
+ uint32_t rbrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rcrfull:1;
+ uint32_t rcrincon:1;
+ uint32_t config_err:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t wred_drop:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rcrto:1;
+ uint32_t rcrthres:1;
+ uint32_t rsrvd:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t rbr_tmout:1;
+ uint32_t rsrvd2:10;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_dma_ent_msk_t, *p_rx_dma_ent_msk_t;
+
+
+/* Receive DMA Control and Status */
+typedef union _rx_dma_ctl_stat_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd:10;
+ uint32_t rbr_tmout:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t mex:1;
+ uint32_t rcrthres:1;
+ uint32_t rcrto:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t wred_drop:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t config_err:1;
+ uint32_t rcrincon:1;
+ uint32_t rcrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rbrfull:1;
+ uint32_t rbrlogpage:1;
+ uint32_t cfiglogpage:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cfiglogpage:1;
+ uint32_t rbrlogpage:1;
+ uint32_t rbrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rcrfull:1;
+ uint32_t rcrincon:1;
+ uint32_t config_err:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t wred_drop:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rcrto:1;
+ uint32_t rcrthres:1;
+ uint32_t mex:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t rbr_tmout:1;
+ uint32_t rsrvd:10;
+#endif
+ } hdw;
+
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ptrread:16;
+ uint32_t pktread:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pktread:16;
+ uint32_t ptrread:16;
+
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd:10;
+ uint32_t rbr_tmout:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t mex:1;
+ uint32_t rcrthres:1;
+ uint32_t rcrto:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t wred_drop:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t config_err:1;
+ uint32_t rcrincon:1;
+ uint32_t rcrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rbrfull:1;
+ uint32_t rbrlogpage:1;
+ uint32_t cfiglogpage:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cfiglogpage:1;
+ uint32_t rbrlogpage:1;
+ uint32_t rbrfull:1;
+ uint32_t rbr_empty:1;
+ uint32_t rcrfull:1;
+ uint32_t rcrincon:1;
+ uint32_t config_err:1;
+ uint32_t rcr_shadow_full:1;
+ uint32_t rbr_pre_empty:1;
+ uint32_t wred_drop:1;
+ uint32_t port_drop_pkt:1;
+ uint32_t rbr_pre_par:1;
+ uint32_t rcr_sha_par:1;
+ uint32_t rcrto:1;
+ uint32_t rcrthres:1;
+ uint32_t mex:1;
+ uint32_t dc_fifo_err:1;
+ uint32_t rcr_ack_err:1;
+ uint32_t rsp_dat_err:1;
+ uint32_t byte_en_bus:1;
+ uint32_t rsp_cnt_err:1;
+ uint32_t rbr_tmout:1;
+ uint32_t rsrvd:10;
+#endif
+ } hdw;
+#endif
+ } bits;
+} rx_dma_ctl_stat_t, *p_rx_dma_ctl_stat_t;
+
+typedef union _rcr_flsh_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:31;
+ uint32_t flsh:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t flsh:1;
+ uint32_t res1_1:31;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rcr_flsh_t, *p_rcr_flsh_t;
+
+
+typedef union _rx_dma_loga_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t multi:1;
+ uint32_t type:3;
+ uint32_t res1:16;
+ uint32_t addr:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t addr:12;
+ uint32_t res1:16;
+ uint32_t type:3;
+ uint32_t multi:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_dma_loga_t, *p_rx_dma_loga_t;
+
+
+typedef union _rx_dma_logb_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t addr_l:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t addr_l:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_dma_logb_t, *p_rx_dma_logb_t;
+
+
+#define RX_DMA_MAILBOX_BYTE_LENGTH 64
+#define RX_DMA_MBOX_UNUSED_1 8
+#define RX_DMA_MBOX_UNUSED_2 16
+
+typedef struct _rxdma_mailbox_t {
+ rx_dma_ctl_stat_t rxdma_ctl_stat; /* 8 bytes */
+ rbr_stat_t rbr_stat; /* 8 bytes */
+ uint32_t rbr_hdl; /* 4 bytes (31:0) */
+ uint32_t rbr_hdh; /* 4 bytes (31:0) */
+ uint32_t resv_1[RX_DMA_MBOX_UNUSED_1];
+ uint32_t rcrstat_c; /* 4 bytes (31:0) */
+ uint32_t rcrstat_b; /* 4 bytes (31:0) */
+ rcrstat_a_t rcrstat_a; /* 8 bytes */
+ uint32_t resv_2[RX_DMA_MBOX_UNUSED_2];
+} rxdma_mailbox_t, *p_rxdma_mailbox_t;
+
+
+
+typedef union _rx_disc_cnt_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:15;
+ uint32_t oflow:1;
+ uint32_t count:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t count:16;
+ uint32_t oflow:1;
+ uint32_t res_1:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_disc_cnt_t, *p_rx_disc_cnt_t;
+
+#define RXMISC_DISCARD_REG (DMC + 0x00090)
+
+#if OLD
+/*
+ * RBR Empty: If the RBR is empty or the prefetch buffer is empty,
+ * packets will be discarded (Each RBR has one).
+ * (16 channels, 0x200)
+ */
+#define RDC_PRE_EMPTY_REG (DMC + 0x000B0)
+#define RDC_PRE_EMPTY_OFFSET(channel) (RDC_PRE_EMPTY_REG + \
+ (DMC_OFFSET(channel))
+
+typedef union _rdc_pre_empty_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:15;
+ uint32_t oflow:1;
+ uint32_t count:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t count:16;
+ uint32_t oflow:1;
+ uint32_t res_1:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdc_pre_empty_t, *p_rdc_pre_empty_t;
+#endif
+
+
+#define FZC_DMC_REG_SIZE 0x20
+#define FZC_DMC_OFFSET(channel) (FZC_DMC_REG_SIZE * channel)
+
+/* WRED discard count register (16, 0x40) */
+#define RED_DIS_CNT_REG (FZC_DMC + 0x30008)
+#define RED_DMC_OFFSET(channel) (0x40 * channel)
+#define RDC_DIS_CNT_OFFSET(rdc) (RED_DIS_CNT_REG + RED_DMC_OFFSET(rdc))
+
+typedef union _red_disc_cnt_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:15;
+ uint32_t oflow:1;
+ uint32_t count:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t count:16;
+ uint32_t oflow:1;
+ uint32_t res_1:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} red_disc_cnt_t, *p_red_disc_cnt_t;
+
+
+#define RDMC_PRE_PAR_ERR_REG (FZC_DMC + 0x00078)
+#define RDMC_SHA_PAR_ERR_REG (FZC_DMC + 0x00080)
+
+typedef union _rdmc_par_err_log {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:16;
+ uint32_t err:1;
+ uint32_t merr:1;
+ uint32_t res:6;
+ uint32_t addr:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t addr:8;
+ uint32_t res:6;
+ uint32_t merr:1;
+ uint32_t err:1;
+ uint32_t res_1:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdmc_par_err_log_t, *p_rdmc_par_err_log_t;
+
+
+/* Used for accessing RDMC Memory */
+#define RDMC_MEM_ADDR_REG (FZC_DMC + 0x00088)
+
+
+typedef union _rdmc_mem_addr {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+
+#define RDMC_MEM_ADDR_PREFETCH 0
+#define RDMC_MEM_ADDR_SHADOW 1
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:23;
+ uint32_t pre_shad:1;
+ uint32_t addr:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t addr:8;
+ uint32_t pre_shad:1;
+ uint32_t res_1:23;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdmc_mem_addr_t, *p_rdmc_mem_addr_t;
+
+
+#define RDMC_MEM_DATA0_REG (FZC_DMC + 0x00090)
+#define RDMC_MEM_DATA1_REG (FZC_DMC + 0x00098)
+#define RDMC_MEM_DATA2_REG (FZC_DMC + 0x000A0)
+#define RDMC_MEM_DATA3_REG (FZC_DMC + 0x000A8)
+#define RDMC_MEM_DATA4_REG (FZC_DMC + 0x000B0)
+
+typedef union _rdmc_mem_data {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t data;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t data;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rdmc_mem_data_t, *p_rdmc_mem_data_t;
+
+
+typedef union _rdmc_mem_access {
+#define RDMC_MEM_READ 1
+#define RDMC_MEM_WRITE 2
+ uint32_t data[5];
+ uint8_t addr;
+ uint8_t location;
+} rdmc_mem_access_t, *p_rdmc_mem_access_t;
+
+
+#define RX_CTL_DAT_FIFO_STAT_REG (FZC_DMC + 0x000B8)
+#define RX_CTL_DAT_FIFO_MASK_REG (FZC_DMC + 0x000C0)
+#define RX_CTL_DAT_FIFO_STAT_DBG_REG (FZC_DMC + 0x000D0)
+
+typedef union _rx_ctl_dat_fifo {
+#define FIFO_EOP_PORT0 0x1
+#define FIFO_EOP_PORT1 0x2
+#define FIFO_EOP_PORT2 0x4
+#define FIFO_EOP_PORT3 0x8
+#define FIFO_EOP_ALL 0xF
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res_1:23;
+ uint32_t id_mismatch:1;
+ uint32_t zcp_eop_err:4;
+ uint32_t ipp_eop_err:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ipp_eop_err:4;
+ uint32_t zcp_eop_err:4;
+ uint32_t id_mismatch:1;
+ uint32_t res_1:23;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_ctl_dat_fifo_mask_t, rx_ctl_dat_fifo_stat_t,
+ rx_ctl_dat_fifo_stat_dbg_t, *p_rx_ctl_dat_fifo_t;
+
+
+
+#define RDMC_TRAINING_VECTOR_REG (FZC_DMC + 0x000C8)
+
+typedef union _rx_training_vect {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+ uint32_t tv;
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} rx_training_vect_t, *p_rx_training_vect_t;
+
+#define RXCTL_IPP_EOP_ERR_MASK 0x0000000FULL
+#define RXCTL_IPP_EOP_ERR_SHIFT 0x0
+#define RXCTL_ZCP_EOP_ERR_MASK 0x000000F0ULL
+#define RXCTL_ZCP_EOP_ERR_SHIFT 0x4
+#define RXCTL_ID_MISMATCH_MASK 0x00000100ULL
+#define RXCTL_ID_MISMATCH_SHIFT 0x8
+
+
+/*
+ * Receive Packet Header Format
+ * Packet header before the packet.
+ * The minimum is 2 bytes and the max size is 18 bytes.
+ */
+/*
+ * Packet header format 0 (2 bytes).
+ */
+typedef union _rx_pkt_hdr0_t {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t inputport:2;
+ uint16_t maccheck:1;
+ uint16_t class:5;
+ uint16_t vlan:1;
+ uint16_t llcsnap:1;
+ uint16_t noport:1;
+ uint16_t badip:1;
+ uint16_t tcamhit:1;
+ uint16_t tres:2;
+ uint16_t tzfvld:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t tzfvld:1;
+ uint16_t tres:2;
+ uint16_t tcamhit:1;
+ uint16_t badip:1;
+ uint16_t noport:1;
+ uint16_t llcsnap:1;
+ uint16_t vlan:1;
+ uint16_t class:5;
+ uint16_t maccheck:1;
+ uint16_t inputport:2;
+#endif
+ } bits;
+} rx_pkt_hdr0_t, *p_rx_pkt_hdr0_t;
+
+
+/*
+ * Packet header format 1.
+ */
+typedef union _rx_pkt_hdr1_b0_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t hwrsvd:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t hwrsvd:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b0_t, *p_rx_pkt_hdr1_b0_t;
+
+typedef union _rx_pkt_hdr1_b1_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t tcammatch:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t tcammatch:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b1_t, *p_rx_pkt_hdr1_b1_t;
+
+typedef union _rx_pkt_hdr1_b2_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t resv:2;
+ uint8_t hashhit:1;
+ uint8_t exact:1;
+ uint8_t hzfvld:1;
+ uint8_t hashidx:3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t hashidx:3;
+ uint8_t hzfvld:1;
+ uint8_t exact:1;
+ uint8_t hashhit:1;
+ uint8_t resv:2;
+#endif
+ } bits;
+} rx_pkt_hdr1_b2_t, *p_rx_pkt_hdr1_b2_t;
+
+typedef union _rx_pkt_hdr1_b3_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t zc_resv:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t zc_resv:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b3_t, *p_rx_pkt_hdr1_b3_t;
+
+typedef union _rx_pkt_hdr1_b4_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t resv:4;
+ uint8_t zflowid:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t zflowid:4;
+ uint8_t resv:4;
+#endif
+ } bits;
+} rx_pkt_hdr1_b4_t, *p_rx_pkt_hdr1_b4_t;
+
+typedef union _rx_pkt_hdr1_b5_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t zflowid:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t zflowid:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b5_t, *p_rx_pkt_hdr1_b5_t;
+
+typedef union _rx_pkt_hdr1_b6_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t hashval2:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t hashval2:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b6_t, *p_rx_pkt_hdr1_b6_t;
+
+typedef union _rx_pkt_hdr1_b7_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t hashval2:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t hashval2:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b7_t, *p_rx_pkt_hdr1_b7_t;
+
+typedef union _rx_pkt_hdr1_b8_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t resv:4;
+ uint8_t h1:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t h1:4;
+ uint8_t resv:4;
+#endif
+ } bits;
+} rx_pkt_hdr1_b8_t, *p_rx_pkt_hdr1_b8_t;
+
+typedef union _rx_pkt_hdr1_b9_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t h1:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t h1:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b9_t, *p_rx_pkt_hdr1_b9_t;
+
+typedef union _rx_pkt_hdr1_b10_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t resv:4;
+ uint8_t h1:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t h1:4;
+ uint8_t resv:4;
+#endif
+ } bits;
+} rx_pkt_hdr1_b10_t, *p_rx_pkt_hdr1_b10_t;
+
+typedef union _rx_pkt_hdr1_b11_b12_t {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t h1_1:8;
+ uint16_t h1_2:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t h1_2:8;
+ uint16_t h1_1:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b11_b12_t, *p_rx_pkt_hdr1_b11_b12_t;
+
+typedef union _rx_pkt_hdr1_b13_t {
+ uint8_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint8_t usr_data:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint8_t usr_data:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b13_t, *p_rx_pkt_hdr1_b13_t;
+
+typedef union _rx_pkt_hdr1_b14_b17_t {
+ uint32_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t usr_data_1:8;
+ uint32_t usr_data_2:8;
+ uint32_t usr_data_3:8;
+ uint32_t usr_data_4:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t usr_data_4:8;
+ uint32_t usr_data_3:8;
+ uint32_t usr_data_2:8;
+ uint32_t usr_data_1:8;
+#endif
+ } bits;
+} rx_pkt_hdr1_b14_b17_t, *p_rx_pkt_hdr1_b14_b17_t;
+
+/* Receive packet header 1 format (18 bytes) */
+typedef struct _rx_pkt_hdr_t {
+ rx_pkt_hdr1_b0_t rx_hdr1_b0;
+ rx_pkt_hdr1_b1_t rx_hdr1_b1;
+ rx_pkt_hdr1_b2_t rx_hdr1_b2;
+ rx_pkt_hdr1_b3_t rx_hdr1_b3;
+ rx_pkt_hdr1_b4_t rx_hdr1_b4;
+ rx_pkt_hdr1_b5_t rx_hdr1_b5;
+ rx_pkt_hdr1_b6_t rx_hdr1_b6;
+ rx_pkt_hdr1_b7_t rx_hdr1_b7;
+ rx_pkt_hdr1_b8_t rx_hdr1_b8;
+ rx_pkt_hdr1_b9_t rx_hdr1_b9;
+ rx_pkt_hdr1_b10_t rx_hdr1_b10;
+ rx_pkt_hdr1_b11_b12_t rx_hdr1_b11_b12;
+ rx_pkt_hdr1_b13_t rx_hdr1_b13;
+ rx_pkt_hdr1_b14_b17_t rx_hdr1_b14_b17;
+} rx_pkt_hdr1_t, *p_rx_pkt_hdr1_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_RXDMA_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_sr_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_sr_hw.h
new file mode 100644
index 0000000000..c487105f26
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_sr_hw.h
@@ -0,0 +1,793 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_SR_HW_H
+#define _SYS_NXGE_NXGE_SR_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESR_NEPTUNE_DEV_ADDR 0x1E
+#define ESR_NEPTUNE_BASE 0
+#define ESR_PORT_ADDR_BASE 0
+#define PCISR_DEV_ADDR 0x1E
+#define PCISR_BASE 0
+#define PCISR_PORT_ADDR_BASE 2
+
+#define PB 0
+
+#define SR_RX_TX_COMMON_CONTROL PB + 0x000
+#define SR_RX_TX_RESET_CONTROL PB + 0x004
+#define SR_RX_POWER_CONTROL PB + 0x008
+#define SR_TX_POWER_CONTROL PB + 0x00C
+#define SR_MISC_POWER_CONTROL PB + 0x010
+#define SR_RX_TX_CONTROL_A PB + 0x100
+#define SR_RX_TX_TUNING_A PB + 0x104
+#define SR_RX_SYNCCHAR_A PB + 0x108
+#define SR_RX_TX_TEST_A PB + 0x10C
+#define SR_GLUE_CONTROL0_A PB + 0x110
+#define SR_GLUE_CONTROL1_A PB + 0x114
+#define SR_RX_TX_CONTROL_B PB + 0x120
+#define SR_RX_TX_TUNING_B PB + 0x124
+#define SR_RX_SYNCCHAR_B PB + 0x128
+#define SR_RX_TX_TEST_B PB + 0x12C
+#define SR_GLUE_CONTROL0_B PB + 0x130
+#define SR_GLUE_CONTROL1_B PB + 0x134
+#define SR_RX_TX_CONTROL_C PB + 0x140
+#define SR_RX_TX_TUNING_C PB + 0x144
+#define SR_RX_SYNCCHAR_C PB + 0x148
+#define SR_RX_TX_TEST_C PB + 0x14C
+#define SR_GLUE_CONTROL0_C PB + 0x150
+#define SR_GLUE_CONTROL1_C PB + 0x154
+#define SR_RX_TX_CONTROL_D PB + 0x160
+#define SR_RX_TX_TUNING_D PB + 0x164
+#define SR_RX_SYNCCHAR_D PB + 0x168
+#define SR_RX_TX_TEST_D PB + 0x16C
+#define SR_GLUE_CONTROL0_D PB + 0x170
+#define SR_GLUE_CONTROL1_D PB + 0x174
+#define SR_RX_TX_TUNING_1_A PB + 0x184
+#define SR_RX_TX_TUNING_1_B PB + 0x1A4
+#define SR_RX_TX_TUNING_1_C PB + 0x1C4
+#define SR_RX_TX_TUNING_1_D PB + 0x1E4
+#define SR_RX_TX_TUNING_2_A PB + 0x204
+#define SR_RX_TX_TUNING_2_B PB + 0x224
+#define SR_RX_TX_TUNING_2_C PB + 0x244
+#define SR_RX_TX_TUNING_2_D PB + 0x264
+#define SR_RX_TX_TUNING_3_A PB + 0x284
+#define SR_RX_TX_TUNING_3_B PB + 0x2A4
+#define SR_RX_TX_TUNING_3_C PB + 0x2C4
+#define SR_RX_TX_TUNING_3_D PB + 0x2E4
+
+/*
+ * Shift right by 1 because the PRM requires that all the serdes register
+ * address be divided by 2
+ */
+#define ESR_NEP_RX_TX_COMMON_CONTROL_L_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_TX_COMMON_CONTROL >> 1))
+#define ESR_NEP_RX_TX_COMMON_CONTROL_H_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_TX_COMMON_CONTROL >> 1)\
+ + 1)
+#define ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_TX_RESET_CONTROL >> 1))
+#define ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_TX_RESET_CONTROL >> 1)\
+ + 1)
+#define ESR_NEP_RX_POWER_CONTROL_L_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_POWER_CONTROL >> 1))
+#define ESR_NEP_RX_POWER_CONTROL_H_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_RX_POWER_CONTROL >> 1) + 1)
+#define ESR_NEP_TX_POWER_CONTROL_L_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_TX_POWER_CONTROL >> 1))
+#define ESR_NEP_TX_POWER_CONTROL_H_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_TX_POWER_CONTROL >> 1) + 1)
+#define ESR_NEP_MISC_POWER_CONTROL_L_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_MISC_POWER_CONTROL >> 1))
+#define ESR_NEP_MISC_POWER_CONTROL_H_ADDR() (ESR_NEPTUNE_BASE +\
+ (SR_MISC_POWER_CONTROL >> 1)\
+ + 1)
+#define ESR_NEP_RX_TX_CONTROL_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_CONTROL_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_CONTROL_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_CONTROL_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_TUNING_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_TUNING_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_SYNCCHAR_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_SYNCCHAR_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_SYNCCHAR_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_SYNCCHAR_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_TEST_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TEST_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_TEST_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TEST_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_GLUE_CONTROL0_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_GLUE_CONTROL0_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_GLUE_CONTROL0_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_GLUE_CONTROL0_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_GLUE_CONTROL1_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_GLUE_CONTROL1_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_GLUE_CONTROL1_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_GLUE_CONTROL1_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_TUNING_1_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_1_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_TUNING_1_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_1_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_TUNING_2_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_2_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_TUNING_2_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_2_A +\
+ (chan * 0x20)) >> 1) + 1
+#define ESR_NEP_RX_TX_TUNING_3_L_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_3_A +\
+ (chan * 0x20)) >> 1)
+#define ESR_NEP_RX_TX_TUNING_3_H_ADDR(chan) ((ESR_NEPTUNE_BASE +\
+ SR_RX_TX_TUNING_3_A +\
+ (chan * 0x20)) >> 1) + 1
+
+typedef union _sr_rx_tx_common_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res3 : 3;
+ uint16_t refclkr_freq : 5;
+ uint16_t res4 : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res4 : 8;
+ uint16_t refclkr_freq : 5;
+ uint16_t res3 : 3;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_common_ctrl_l;
+
+typedef union _sr_rx_tx_common_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 5;
+ uint16_t tdmaster : 3;
+ uint16_t tp : 2;
+ uint16_t tz : 2;
+ uint16_t res2 : 2;
+ uint16_t revlbrefsel : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t revlbrefsel : 2;
+ uint16_t res2 : 2;
+ uint16_t tz : 2;
+ uint16_t tp : 2;
+ uint16_t tdmaster : 3;
+ uint16_t res1 : 5;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_common_ctrl_h;
+
+
+/* RX TX Common Control Register field values */
+
+#define TDMASTER_LANE_A 0
+#define TDMASTER_LANE_B 1
+#define TDMASTER_LANE_C 2
+#define TDMASTER_LANE_D 3
+
+#define REVLBREFSEL_GBT_RBC_A_O 0
+#define REVLBREFSEL_GBT_RBC_B_O 1
+#define REVLBREFSEL_GBT_RBC_C_O 2
+#define REVLBREFSEL_GBT_RBC_D_O 3
+
+#define REFCLKR_FREQ_SIM 0
+#define REFCLKR_FREQ_53_125 0x1
+#define REFCLKR_FREQ_62_5 0x3
+#define REFCLKR_FREQ_70_83 0x4
+#define REFCLKR_FREQ_75 0x5
+#define REFCLKR_FREQ_78_125 0x6
+#define REFCLKR_FREQ_79_6875 0x7
+#define REFCLKR_FREQ_83_33 0x8
+#define REFCLKR_FREQ_85 0x9
+#define REFCLKR_FREQ_100 0xA
+#define REFCLKR_FREQ_104_17 0xB
+#define REFCLKR_FREQ_106_25 0xC
+#define REFCLKR_FREQ_120 0xF
+#define REFCLKR_FREQ_125 0x10
+#define REFCLKR_FREQ_127_5 0x11
+#define REFCLKR_FREQ_141_67 0x13
+#define REFCLKR_FREQ_150 0x15
+#define REFCLKR_FREQ_156_25 0x16
+#define REFCLKR_FREQ_159_375 0x17
+#define REFCLKR_FREQ_170 0x19
+#define REFCLKR_FREQ_212_5 0x1E
+
+typedef union _sr_rx_tx_reset_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t rxreset_0a : 1;
+ uint16_t rxreset_0b : 1;
+ uint16_t rxreset_0c : 1;
+ uint16_t rxreset_0d : 1;
+ uint16_t rxreset_1a : 1;
+ uint16_t rxreset_1b : 1;
+ uint16_t rxreset_1c : 1;
+ uint16_t rxreset_1d : 1;
+ uint16_t rxreset_2a : 1;
+ uint16_t rxreset_2b : 1;
+ uint16_t rxreset_2c : 1;
+ uint16_t rxreset_2d : 1;
+ uint16_t rxreset_3a : 1;
+ uint16_t rxreset_3b : 1;
+ uint16_t rxreset_3c : 1;
+ uint16_t rxreset_3d : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t rxreset_3d : 1;
+ uint16_t rxreset_3c : 1;
+ uint16_t rxreset_3b : 1;
+ uint16_t rxreset_3a : 1;
+ uint16_t rxreset_2d : 1;
+ uint16_t rxreset_2c : 1;
+ uint16_t rxreset_2b : 1;
+ uint16_t rxreset_2a : 1;
+ uint16_t rxreset_1d : 1;
+ uint16_t rxreset_1c : 1;
+ uint16_t rxreset_1b : 1;
+ uint16_t rxreset_1a : 1;
+ uint16_t rxreset_0d : 1;
+ uint16_t rxreset_0c : 1;
+ uint16_t rxreset_0b : 1;
+ uint16_t rxreset_0a : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_reset_ctrl_l;
+
+
+typedef union _sr_rx_tx_reset_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t txreset_0a : 1;
+ uint16_t txreset_0b : 1;
+ uint16_t txreset_0c : 1;
+ uint16_t txreset_0d : 1;
+ uint16_t txreset_1a : 1;
+ uint16_t txreset_1b : 1;
+ uint16_t txreset_1c : 1;
+ uint16_t txreset_1d : 1;
+ uint16_t txreset_2a : 1;
+ uint16_t txreset_2b : 1;
+ uint16_t txreset_2c : 1;
+ uint16_t txreset_2d : 1;
+ uint16_t txreset_3a : 1;
+ uint16_t txreset_3b : 1;
+ uint16_t txreset_3c : 1;
+ uint16_t txreset_3d : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t txreset_3d : 1;
+ uint16_t txreset_3c : 1;
+ uint16_t txreset_3b : 1;
+ uint16_t txreset_3a : 1;
+ uint16_t txreset_2d : 1;
+ uint16_t txreset_2c : 1;
+ uint16_t txreset_2b : 1;
+ uint16_t txreset_2a : 1;
+ uint16_t txreset_1d : 1;
+ uint16_t txreset_1c : 1;
+ uint16_t txreset_1b : 1;
+ uint16_t txreset_1a : 1;
+ uint16_t txreset_0d : 1;
+ uint16_t txreset_0c : 1;
+ uint16_t txreset_0b : 1;
+ uint16_t txreset_0a : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_reset_ctrl_h;
+
+typedef union _sr_rx_power_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t pdrxlos_0a : 1;
+ uint16_t pdrxlos_0b : 1;
+ uint16_t pdrxlos_0c : 1;
+ uint16_t pdrxlos_0d : 1;
+ uint16_t pdrxlos_1a : 1;
+ uint16_t pdrxlos_1b : 1;
+ uint16_t pdrxlos_1c : 1;
+ uint16_t pdrxlos_1d : 1;
+ uint16_t pdrxlos_2a : 1;
+ uint16_t pdrxlos_2b : 1;
+ uint16_t pdrxlos_2c : 1;
+ uint16_t pdrxlos_2d : 1;
+ uint16_t pdrxlos_3a : 1;
+ uint16_t pdrxlos_3b : 1;
+ uint16_t pdrxlos_3c : 1;
+ uint16_t pdrxlos_3d : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t pdrxlos_3d : 1;
+ uint16_t pdrxlos_3c : 1;
+ uint16_t pdrxlos_3b : 1;
+ uint16_t pdrxlos_3a : 1;
+ uint16_t pdrxlos_2d : 1;
+ uint16_t pdrxlos_2c : 1;
+ uint16_t pdrxlos_2b : 1;
+ uint16_t pdrxlos_2a : 1;
+ uint16_t pdrxlos_1d : 1;
+ uint16_t pdrxlos_1c : 1;
+ uint16_t pdrxlos_1b : 1;
+ uint16_t pdrxlos_1a : 1;
+ uint16_t pdrxlos_0d : 1;
+ uint16_t pdrxlos_0c : 1;
+ uint16_t pdrxlos_0b : 1;
+ uint16_t pdrxlos_0a : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_power_ctrl_l_t;
+
+
+typedef union _sr_rx_power_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t pdownr_0a : 1;
+ uint16_t pdownr_0b : 1;
+ uint16_t pdownr_0c : 1;
+ uint16_t pdownr_0d : 1;
+ uint16_t pdownr_1a : 1;
+ uint16_t pdownr_1b : 1;
+ uint16_t pdownr_1c : 1;
+ uint16_t pdownr_1d : 1;
+ uint16_t pdownr_2a : 1;
+ uint16_t pdownr_2b : 1;
+ uint16_t pdownr_2c : 1;
+ uint16_t pdownr_2d : 1;
+ uint16_t pdownr_3a : 1;
+ uint16_t pdownr_3b : 1;
+ uint16_t pdownr_3c : 1;
+ uint16_t pdownr_3d : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t pdownr_3d : 1;
+ uint16_t pdownr_3c : 1;
+ uint16_t pdownr_3b : 1;
+ uint16_t pdownr_3a : 1;
+ uint16_t pdownr_2d : 1;
+ uint16_t pdownr_2c : 1;
+ uint16_t pdownr_2b : 1;
+ uint16_t pdownr_2a : 1;
+ uint16_t pdownr_1d : 1;
+ uint16_t pdownr_1c : 1;
+ uint16_t pdownr_1b : 1;
+ uint16_t pdownr_1a : 1;
+ uint16_t pdownr_0d : 1;
+ uint16_t pdownr_0c : 1;
+ uint16_t pdownr_0b : 1;
+ uint16_t pdownr_0a : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_power_ctrl_h_t;
+
+typedef union _sr_tx_power_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 8;
+ uint16_t pdownppll0 : 1;
+ uint16_t pdownppll1 : 1;
+ uint16_t pdownppll2 : 1;
+ uint16_t pdownppll3 : 1;
+ uint16_t res2 : 4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res2 : 4;
+ uint16_t pdownppll3 : 1;
+ uint16_t pdownppll2 : 1;
+ uint16_t pdownppll1 : 1;
+ uint16_t pdownppll0 : 1;
+ uint16_t res1 : 8;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_tx_power_ctrl_l_t;
+
+typedef union _sr_tx_power_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t pdownt_0a : 1;
+ uint16_t pdownt_0b : 1;
+ uint16_t pdownt_0c : 1;
+ uint16_t pdownt_0d : 1;
+ uint16_t pdownt_1a : 1;
+ uint16_t pdownt_1b : 1;
+ uint16_t pdownt_1c : 1;
+ uint16_t pdownt_1d : 1;
+ uint16_t pdownt_2a : 1;
+ uint16_t pdownt_2b : 1;
+ uint16_t pdownt_2c : 1;
+ uint16_t pdownt_2d : 1;
+ uint16_t pdownt_3a : 1;
+ uint16_t pdownt_3b : 1;
+ uint16_t pdownt_3c : 1;
+ uint16_t pdownt_3d : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t pdownt_3d : 1;
+ uint16_t pdownt_3c : 1;
+ uint16_t pdownt_3b : 1;
+ uint16_t pdownt_3a : 1;
+ uint16_t pdownt_2d : 1;
+ uint16_t pdownt_2c : 1;
+ uint16_t pdownt_2b : 1;
+ uint16_t pdownt_2a : 1;
+ uint16_t pdownt_1d : 1;
+ uint16_t pdownt_1c : 1;
+ uint16_t pdownt_1b : 1;
+ uint16_t pdownt_1a : 1;
+ uint16_t pdownt_0d : 1;
+ uint16_t pdownt_0c : 1;
+ uint16_t pdownt_0b : 1;
+ uint16_t pdownt_0a : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_tx_power_ctrl_h_t;
+
+typedef union _sr_misc_power_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 3;
+ uint16_t pdrtrim : 1;
+ uint16_t pdownpecl0 : 1;
+ uint16_t pdownpecl1 : 1;
+ uint16_t pdownpecl2 : 1;
+ uint16_t pdownpecl3 : 1;
+ uint16_t pdownppll0 : 1;
+ uint16_t pdownppll1 : 1;
+ uint16_t pdownppll2 : 1;
+ uint16_t pdownppll3 : 1;
+ uint16_t res2 : 4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res2 : 4;
+ uint16_t pdownppll3 : 1;
+ uint16_t pdownppll2 : 1;
+ uint16_t pdownppll1 : 1;
+ uint16_t pdownppll0 : 1;
+ uint16_t pdownpecl3 : 1;
+ uint16_t pdownpecl2 : 1;
+ uint16_t pdownpecl1 : 1;
+ uint16_t pdownpecl0 : 1;
+ uint16_t pdrtrim : 1;
+ uint16_t res1 : 3;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_misc_power_ctrl_l_t;
+
+typedef union _misc_power_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t pdclkout0 : 1;
+ uint16_t pdclkout1 : 1;
+ uint16_t pdclkout2 : 1;
+ uint16_t pdclkout3 : 1;
+ uint16_t res1 : 12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res1 : 12;
+ uint16_t pdclkout3 : 1;
+ uint16_t pdclkout2 : 1;
+ uint16_t pdclkout1 : 1;
+ uint16_t pdclkout0 : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} misc_power_ctrl_h_t;
+
+typedef union _sr_rx_tx_ctrl_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 2;
+ uint16_t rxpreswin : 2;
+ uint16_t res2 : 1;
+ uint16_t risefall : 3;
+ uint16_t res3 : 7;
+ uint16_t enstretch : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t enstretch : 1;
+ uint16_t res3 : 7;
+ uint16_t risefall : 3;
+ uint16_t res2 : 1;
+ uint16_t rxpreswin : 2;
+ uint16_t res1 : 2;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_ctrl_l_t;
+
+typedef union _sr_rx_tx_ctrl_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t biascntl : 1;
+ uint16_t res1 : 5;
+ uint16_t tdenfifo : 1;
+ uint16_t tdws20 : 1;
+ uint16_t vmuxlo : 2;
+ uint16_t vpulselo : 2;
+ uint16_t res2 : 4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res2 : 4;
+ uint16_t vpulselo : 2;
+ uint16_t vmuxlo : 2;
+ uint16_t tdws20 : 1;
+ uint16_t tdenfifo : 1;
+ uint16_t res1 : 5;
+ uint16_t biascntl : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_ctrl_h_t;
+
+#define RXPRESWIN_52US_300BITTIMES 0
+#define RXPRESWIN_53US_300BITTIMES 1
+#define RXPRESWIN_54US_300BITTIMES 2
+#define RXPRESWIN_55US_300BITTIMES 3
+
+typedef union _sr_rx_tx_tuning_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t rxeq : 4;
+ uint16_t res1 : 12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res1 : 12;
+ uint16_t rxeq : 4;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_tuning_l_t;
+
+typedef union _sr_rx_tx_tuning_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 8;
+ uint16_t rp : 2;
+ uint16_t rz : 2;
+ uint16_t vtxlo : 4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t vtxlo : 4;
+ uint16_t rz : 2;
+ uint16_t rp : 2;
+ uint16_t res1 : 8;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_tuning_h_t;
+
+typedef union _sr_rx_syncchar_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t syncchar_0_3 : 4;
+ uint16_t res1 : 2;
+ uint16_t syncmask : 10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t syncmask : 10;
+ uint16_t res1 : 2;
+ uint16_t syncchar_0_3 : 4;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_syncchar_l_t;
+
+typedef union _sr_rx_syncchar_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 1;
+ uint16_t syncpol : 1;
+ uint16_t res2 : 8;
+ uint16_t syncchar_4_10 : 6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t syncchar_4_10 : 6;
+ uint16_t res2 : 8;
+ uint16_t syncpol : 1;
+ uint16_t res1 : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_syncchar_h_t;
+
+typedef union _sr_rx_tx_test_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 15;
+ uint16_t ref50 : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t ref50 : 1;
+ uint16_t res1 : 15;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_test_l_t;
+
+typedef union _sr_rx_tx_test_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 5;
+ uint16_t selftest : 3;
+ uint16_t res2 : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res2 : 8;
+ uint16_t selftest : 3;
+ uint16_t res1 : 5;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_rx_tx_test_h_t;
+
+typedef union _sr_glue_ctrl0_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t rxlos_test : 1;
+ uint16_t res1 : 1;
+ uint16_t rxlosenable : 1;
+ uint16_t fastresync : 1;
+ uint16_t samplerate : 4;
+ uint16_t thresholdcount : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t thresholdcount : 8;
+ uint16_t samplerate : 4;
+ uint16_t fastresync : 1;
+ uint16_t rxlosenable : 1;
+ uint16_t res1 : 1;
+ uint16_t rxlos_test : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_glue_ctrl0_l_t;
+
+typedef union _sr_glue_ctrl0_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 5;
+ uint16_t bitlocktime : 3;
+ uint16_t res2 : 8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res2 : 8;
+ uint16_t bitlocktime : 3;
+ uint16_t res1 : 5;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_glue_ctrl0_h_t;
+
+#define BITLOCKTIME_64_CYCLES 0
+#define BITLOCKTIME_128_CYCLES 1
+#define BITLOCKTIME_256_CYCLES 2
+#define BITLOCKTIME_300_CYCLES 3
+#define BITLOCKTIME_384_CYCLES 4
+#define BITLOCKTIME_512_CYCLES 5
+#define BITLOCKTIME_1024_CYCLES 6
+#define BITLOCKTIME_2048_CYCLES 7
+
+typedef union _sr_glue_ctrl1_l {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t res1 : 14;
+ uint16_t inittime : 2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t inittime : 2;
+ uint16_t res1 : 14;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} sr_glue_ctrl1_l_t;
+
+typedef union glue_ctrl1_h {
+ uint16_t value;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint16_t termr_cfg : 2;
+ uint16_t termt_cfg : 2;
+ uint16_t rtrimen : 2;
+ uint16_t res1 : 10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint16_t res1 : 10;
+ uint16_t rtrimen : 2;
+ uint16_t termt_cfg : 2;
+ uint16_t termr_cfg : 2;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } bits;
+} glue_ctrl1_h_t;
+
+#define TERM_CFG_67OHM 0
+#define TERM_CFG_72OHM 1
+#define TERM_CFG_80OHM 2
+#define TERM_CFG_87OHM 3
+#define TERM_CFG_46OHM 4
+#define TERM_CFG_48OHM 5
+#define TERM_CFG_52OHM 6
+#define TERM_CFG_55OHM 7
+
+#define INITTIME_60US 0
+#define INITTIME_120US 1
+#define INITTIME_240US 2
+#define INITTIME_480US 3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_SR_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_str_cfg.h b/usr/src/uts/sun4v/sys/nxge/nxge_str_cfg.h
new file mode 100644
index 0000000000..b2649111ec
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_str_cfg.h
@@ -0,0 +1,75 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_STR_CFG_H
+#define _SYS_NXGE_NXGE_STR_CFG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following definition controls on a per stream basis
+ * wether the stream will use the interrupt context to push
+ * packets to the next layer, use a streams service routine
+ * or will bypass streams completely using caller provided
+ * vectors.
+ * This M_CTL definition applies only to in kernel modules.
+ */
+#ifdef _KERNEL
+typedef enum {
+ use_intr,
+ use_rsrv,
+ use_str_bypass
+} put_cfg;
+
+typedef enum {
+ use_start,
+ use_start_serial
+} start_cfg;
+
+/*
+ * The following data structure allows an independent driver/module
+ * using the dpli driver to send and M_CTL message to the driver
+ * which will alter the datapath mode of operation of the driver.
+ */
+typedef struct _str_cfg_t {
+ uint_t cmd; /* M_CTL message magic */
+ put_cfg cfg; /* data path configuration. */
+ int (*canputp)(); /* Caller replacement for canputnext */
+ void (*putp)(); /* Caller replacement for putnext */
+} str_cfg_t, *p_str_cfg_t;
+
+#define STR_CFG_M_CTL 0xCEDEC0DE /* M_CTL command for this feature. */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_STR_CFG_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_txc.h b/usr/src/uts/sun4v/sys/nxge/nxge_txc.h
new file mode 100644
index 0000000000..74ec1f2d01
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_txc.h
@@ -0,0 +1,83 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_TXC_H
+#define _SYS_NXGE_NXGE_TXC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/nxge/nxge_txc_hw.h>
+#include <npi_txc.h>
+
+/* Suggested by hardware team 7/19/2006 */
+#define TXC_DMA_MAX_BURST_DEFAULT 1530 /* Max burst used by DRR */
+
+typedef struct _txc_errlog {
+ txc_ro_states_t ro_st;
+ txc_sf_states_t sf_st;
+} txc_errlog_t;
+
+typedef struct _nxge_txc_stats {
+ uint32_t pkt_stuffed;
+ uint32_t pkt_xmit;
+ uint32_t ro_correct_err;
+ uint32_t ro_uncorrect_err;
+ uint32_t sf_correct_err;
+ uint32_t sf_uncorrect_err;
+ uint32_t address_failed;
+ uint32_t dma_failed;
+ uint32_t length_failed;
+ uint32_t pkt_assy_dead;
+ uint32_t reorder_err;
+ txc_errlog_t errlog;
+} nxge_txc_stats_t, *p_nxge_txc_stats_t;
+
+typedef struct _nxge_txc {
+ uint32_t dma_max_burst;
+ uint32_t dma_length;
+ uint32_t training;
+ uint8_t debug_select;
+ uint64_t control_status;
+ uint64_t port_dma_list;
+ nxge_txc_stats_t *txc_stats;
+} nxge_txc_t, *p_nxge_txc_t;
+
+/*
+ * Transmit Controller (TXC) prototypes.
+ */
+nxge_status_t nxge_txc_init(p_nxge_t);
+nxge_status_t nxge_txc_uninit(p_nxge_t);
+nxge_status_t nxge_txc_handle_sys_errors(p_nxge_t);
+void nxge_txc_inject_err(p_nxge_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_TXC_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_txc_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_txc_hw.h
new file mode 100644
index 0000000000..712941037b
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_txc_hw.h
@@ -0,0 +1,1270 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_TXC_HW_H
+#define _SYS_NXGE_NXGE_TXC_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+/* Transmit Ring Scheduler Registers */
+#define TXC_PORT_DMA_ENABLE_REG (FZC_TXC + 0x20028)
+#define TXC_PORT_DMA_LIST 0 /* RW bit 23:0 */
+#define TXC_DMA_DMA_LIST_MASK 0x0000000000FFFFFFULL
+#define TXC_DMA_DMA_LIST_MASK_N2 0x000000000000FFFFULL
+
+typedef union _txc_port_enable_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:8;
+ uint32_t port_dma_list:24;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port_dma_list:24;
+ uint32_t res:8;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_port_enable_t, *p_txc_port_enable_t;
+
+typedef union _txc_port_enable_n2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:16;
+ uint32_t port_dma_list:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port_dma_list:16;
+ uint32_t res:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_port_enable_n2_t, *p_txc_port_enable_n2_t;
+
+/* Transmit Controller - Registers */
+#define TXC_FZC_OFFSET 0x1000
+#define TXC_FZC_PORT_OFFSET(port) (port * TXC_FZC_OFFSET)
+#define TXC_FZC_CHANNEL_OFFSET(channel) (channel * TXC_FZC_OFFSET)
+#define TXC_FZC_REG_CN_OFFSET(x, cn) (x + TXC_FZC_CHANNEL_OFFSET(cn))
+
+#define TXC_FZC_CONTROL_OFFSET 0x100
+#define TXC_FZC_CNTL_PORT_OFFSET(port) (port * TXC_FZC_CONTROL_OFFSET)
+#define TXC_FZC_REG_PT_OFFSET(x, pt) (x + TXC_FZC_CNTL_PORT_OFFSET(pt))
+
+#define TXC_DMA_MAX_BURST_REG (FZC_TXC + 0x00000)
+#define TXC_DMA_MAX_BURST_SHIFT 0 /* RW bit 19:0 */
+#define TXC_DMA_MAX_BURST_MASK 0x00000000000FFFFFULL
+
+#define TXC_MAX_BURST_OFFSET(channel) (TXC_DMA_MAX_BURST_REG + \
+ (channel * TXC_FZC_OFFSET))
+
+typedef union _txc_dma_max_burst_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:12;
+ uint32_t dma_max_burst:20;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dma_max_burst:20;
+ uint32_t res:12;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_dma_max_burst_t, *p_txc_dma_max_burst_t;
+
+/* DRR Performance Monitoring Register */
+#define TXC_DMA_MAX_LENGTH_REG (FZC_TXC + 0x00008)
+#define TXC_DMA_MAX_LENGTH_SHIFT /* RW bit 27:0 */
+#define TXC_DMA_MAX_LENGTH_MASK 0x000000000FFFFFFFULL
+
+#define TXC_DMA_MAX_LEN_OFFSET(channel) (TXC_DMA_MAX_LENGTH_REG + \
+ (channel * TXC_FZC_OFFSET))
+
+typedef union _txc_dma_max_length_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:4;
+ uint32_t dma_length:28;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dma_length:28;
+ uint32_t res:4;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_dma_max_length_t, *p_txc_dma_max_length_t;
+
+
+#define TXC_CONTROL_REG (FZC_TXC + 0x20000)
+#define TXC_DMA_LENGTH_SHIFT 0 /* RW bit 27:0 */
+#define TXC_DMA_LENGTH_MASK 0x000000000FFFFFFFULL
+
+typedef union _txc_control_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:27;
+ uint32_t txc_enabled:1;
+ uint32_t port3_enabled:1;
+ uint32_t port2_enabled:1;
+ uint32_t port1_enabled:1;
+ uint32_t port0_enabled:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_enabled:1;
+ uint32_t port1_enabled:1;
+ uint32_t port2_enabled:1;
+ uint32_t port3_enabled:1;
+ uint32_t txc_enabled:1;
+ uint32_t res:27;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_control_t, *p_txc_control_t;
+
+typedef union _txc_control_n2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:27;
+ uint32_t txc_enabled:1;
+ uint32_t res1:2;
+ uint32_t port1_enabled:1;
+ uint32_t port0_enabled:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_enabled:1;
+ uint32_t port1_enabled:1;
+ uint32_t res1:2;
+ uint32_t txc_enabled:1;
+ uint32_t res:27;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_control_n2_t, *p_txc_control_n2_t;
+
+
+#define TXC_TRAINING_REG (FZC_TXC + 0x20008)
+#define TXC_TRAINING_VECTOR 0 /* RW bit 32:0 */
+#define TXC_TRAINING_VECTOR_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_training_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t txc_training_vector:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t txc_training_vector:32;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_training_t, *p_txc_training_t;
+
+
+#define TXC_DEBUG_SELECT_REG (FZC_TXC + 0x20010)
+#define TXC_DEBUG_SELECT_SHIFT 0 /* WO bit 5:0 */
+#define TXC_DEBUG_SELECT_MASK 0x000000000000003FULL
+
+typedef union _txc_debug_select_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:26;
+ uint32_t debug_select:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t debug_select:6;
+ uint32_t res:26;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_debug_select_t, *p_txc_debug_select_t;
+
+
+#define TXC_MAX_REORDER_REG (FZC_TXC + 0x20018)
+#define TXC_MAX_REORDER_MASK_2 (0xf)
+#define TXC_MAX_REORDER_MASK_4 (0x7)
+#define TXC_MAX_REORDER_SHIFT_BITS 8
+#define TXC_MAX_REORDER_SHIFT(port) (port * (TXC_MAX_REORDER_SHIFT_BITS))
+
+typedef union _txc_max_reorder_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t resv3:4;
+ uint32_t port3:4;
+ uint32_t resv2:4;
+ uint32_t port2:4;
+ uint32_t resv1:4;
+ uint32_t port1:4;
+ uint32_t resv0:4;
+ uint32_t port0:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0:4;
+ uint32_t resv0:4;
+ uint32_t port1:4;
+ uint32_t resv1:4;
+ uint32_t port2:4;
+ uint32_t resv2:4;
+ uint32_t port3:4;
+ uint32_t resv3:4;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_max_reorder_t, *p_txc_max_reorder_t;
+
+
+#define TXC_PORT_CTL_REG (FZC_TXC + 0x20020) /* RO */
+#define TXC_PORT_CTL_OFFSET(port) (TXC_PORT_CTL_REG + \
+ (port * TXC_FZC_CONTROL_OFFSET))
+#define TXC_PORT_CNTL_CLEAR 0x1
+
+typedef union _txc_port_ctl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:31;
+ uint32_t clr_all_stat:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t clr_all_stat:1;
+ uint32_t rsvd:31;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_port_ctl_t, *p_txc_port_ctl_t;
+
+#define TXC_PKT_STUFFED_REG (FZC_TXC + 0x20030)
+#define TXC_PKT_STUFF_PKTASY_SHIFT 16 /* RW bit 16:0 */
+#define TXC_PKT_STUFF_PKTASY_MASK 0x000000000000FFFFULL
+#define TXC_PKT_STUFF_REORDER_SHIFT 0 /* RW bit 31:16 */
+#define TXC_PKT_STUFF_REORDER_MASK 0x00000000FFFF0000ULL
+
+typedef union _txc_pkt_stuffed_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pkt_pro_reorder:16;
+ uint32_t pkt_proc_pktasy:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_proc_pktasy:16;
+ uint32_t pkt_pro_reorder:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_pkt_stuffed_t, *p_txc_pkt_stuffed_t;
+
+
+#define TXC_PKT_XMIT_REG (FZC_TXC + 0x20038)
+#define TXC_PKTS_XMIT_SHIFT 0 /* RW bit 15:0 */
+#define TXC_PKTS_XMIT_MASK 0x000000000000FFFFULL
+#define TXC_BYTES_XMIT_SHIFT 16 /* RW bit 31:16 */
+#define TXC_BYTES_XMIT_MASK 0x00000000FFFF0000ULL
+
+typedef union _txc_pkt_xmit_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t bytes_transmitted:16;
+ uint32_t pkts_transmitted:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkts_transmitted:16;
+ uint32_t bytes_transmitted:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_pkt_xmit, *p_txc_pkt_xmit;
+
+
+/* count 4 step 0x00100 */
+#define TXC_ROECC_CTL_REG (FZC_TXC + 0x20040)
+#define TXC_ROECC_CTL_OFFSET(port) (TXC_ROECC_CTL_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_roecc_ctl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t disable_ue_error:1;
+ uint32_t rsvd:13;
+ uint32_t double_bit_err:1;
+ uint32_t single_bit_err:1;
+ uint32_t rsvd_2:5;
+ uint32_t all_pkts:1;
+ uint32_t alternate_pkts:1;
+ uint32_t one_pkt:1;
+ uint32_t rsvd_3:5;
+ uint32_t last_line_pkt:1;
+ uint32_t second_line_pkt:1;
+ uint32_t firstd_line_pkt:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t firstd_line_pkt:1;
+ uint32_t second_line_pkt:1;
+ uint32_t last_line_pkt:1;
+ uint32_t rsvd_3:5;
+ uint32_t one_pkt:1;
+ uint32_t alternate_pkts:1;
+ uint32_t all_pkts:1;
+ uint32_t rsvd_2:5;
+ uint32_t single_bit_err:1;
+ uint32_t double_bit_err:1;
+ uint32_t rsvd:13;
+ uint32_t disable_ue_error:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_roecc_ctl_t, *p_txc_roecc_ctl_t;
+
+
+#define TXC_ROECC_ST_REG (FZC_TXC + 0x20048)
+
+#define TXC_ROECC_ST_OFFSET(port) (TXC_ROECC_ST_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_roecc_st_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t clr_st:1;
+ uint32_t res:13;
+ uint32_t correct_error:1;
+ uint32_t uncorrect_error:1;
+ uint32_t rsvd:6;
+ uint32_t ecc_address:10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ecc_address:10;
+ uint32_t rsvd:6;
+ uint32_t uncorrect_error:1;
+ uint32_t correct_error:1;
+ uint32_t res:13;
+ uint32_t clr_st:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_roecc_st_t, *p_txc_roecc_st_t;
+
+
+#define TXC_RO_DATA0_REG (FZC_TXC + 0x20050)
+#define TXC_RO_DATA0_OFFSET(port) (TXC_RO_DATA0_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_data0_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_ecc_data0:32; /* ro_ecc_data[31:0] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_ecc_data0:32; /* ro_ecc_data[31:0] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_data0_t, *p_txc_ro_data0_t;
+
+#define TXC_RO_DATA1_REG (FZC_TXC + 0x20058)
+#define TXC_RO_DATA1_OFFSET(port) (TXC_RO_DATA1_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_data1_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_ecc_data1:32; /* ro_ecc_data[63:32] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_ecc_data1:32; /* ro_ecc_data[31:32] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_data1_t, *p_txc_ro_data1_t;
+
+
+#define TXC_RO_DATA2_REG (FZC_TXC + 0x20060)
+
+#define TXC_RO_DATA2_OFFSET(port) (TXC_RO_DATA2_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_data2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_ecc_data2:32; /* ro_ecc_data[95:64] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_ecc_data2:32; /* ro_ecc_data[95:64] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_data2_t, *p_txc_ro_data2_t;
+
+#define TXC_RO_DATA3_REG (FZC_TXC + 0x20068)
+#define TXC_RO_DATA3_OFFSET(port) (TXC_RO_DATA3_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_data3_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_ecc_data3:32; /* ro_ecc_data[127:96] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_ecc_data3:32; /* ro_ecc_data[127:96] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_data3_t, *p_txc_ro_data3_t;
+
+#define TXC_RO_DATA4_REG (FZC_TXC + 0x20070)
+#define TXC_RO_DATA4_OFFSET(port) (TXC_RO_DATA4_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_data4_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_ecc_data4:32; /* ro_ecc_data[151:128] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_ecc_data4:32; /* ro_ecc_data[151:128] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_data4_t, *p_txc_ro_data4_t;
+
+/* count 4 step 0x00100 */
+#define TXC_SFECC_CTL_REG (FZC_TXC + 0x20078)
+#define TXC_SFECC_CTL_OFFSET(port) (TXC_SFECC_CTL_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sfecc_ctl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t disable_ue_error:1;
+ uint32_t rsvd:13;
+ uint32_t double_bit_err:1;
+ uint32_t single_bit_err:1;
+ uint32_t rsvd_2:5;
+ uint32_t all_pkts:1;
+ uint32_t alternate_pkts:1;
+ uint32_t one_pkt:1;
+ uint32_t rsvd_3:5;
+ uint32_t last_line_pkt:1;
+ uint32_t second_line_pkt:1;
+ uint32_t firstd_line_pkt:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t firstd_line_pkt:1;
+ uint32_t second_line_pkt:1;
+ uint32_t last_line_pkt:1;
+ uint32_t rsvd_3:5;
+ uint32_t one_pkt:1;
+ uint32_t alternate_pkts:1;
+ uint32_t all_pkts:1;
+ uint32_t rsvd_2:5;
+ uint32_t single_bit_err:1;
+ uint32_t double_bit_err:1;
+ uint32_t rsvd:13;
+ uint32_t disable_ue_error:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sfecc_ctl_t, *p_txc_sfecc_ctl_t;
+
+#define TXC_SFECC_ST_REG (FZC_TXC + 0x20080)
+#define TXC_SFECC_ST_OFFSET(port) (TXC_SFECC_ST_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sfecc_st_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t clr_st:1;
+ uint32_t res:13;
+ uint32_t correct_error:1;
+ uint32_t uncorrect_error:1;
+ uint32_t rsvd:6;
+ uint32_t ecc_address:10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ecc_address:10;
+ uint32_t rsvd:6;
+ uint32_t uncorrect_error:1;
+ uint32_t correct_error:1;
+ uint32_t res:13;
+ uint32_t clr_st:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sfecc_st_t, *p_txc_sfecc_st_t;
+
+#define TXC_SF_DATA0_REG (FZC_TXC + 0x20088)
+#define TXC_SF_DATA0_OFFSET(port) (TXC_SF_DATA0_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sf_data0_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sf_ecc_data0:32; /* sf_ecc_data[31:0] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sf_ecc_data0:32; /* sf_ecc_data[31:0] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sf_data0_t, *p_txc_sf_data0_t;
+
+#define TXC_SF_DATA1_REG (FZC_TXC + 0x20090)
+#define TXC_SF_DATA1_OFFSET(port) (TXC_SF_DATA1_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sf_data1_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sf_ecc_data1:32; /* sf_ecc_data[63:32] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sf_ecc_data1:32; /* sf_ecc_data[31:32] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sf_data1_t, *p_txc_sf_data1_t;
+
+
+#define TXC_SF_DATA2_REG (FZC_TXC + 0x20098)
+#define TXC_SF_DATA2_OFFSET(port) (TXC_SF_DATA2_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sf_data2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sf_ecc_data2:32; /* sf_ecc_data[95:64] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sf_ecc_data2:32; /* sf_ecc_data[95:64] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sf_data2_t, *p_txc_sf_data2_t;
+
+#define TXC_SF_DATA3_REG (FZC_TXC + 0x200A0)
+#define TXC_SF_DATA3_OFFSET(port) (TXC_SF_DATA3_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sf_data3_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sf_ecc_data3:32; /* sf_ecc_data[127:96] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sf_ecc_data3:32; /* sf_ecc_data[127:96] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sf_data3_t, *p_txc_sf_data3_t;
+
+#define TXC_SF_DATA4_REG (FZC_TXC + 0x200A8)
+#define TXC_SF_DATA4_OFFSET(port) (TXC_SF_DATA4_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_sf_data4_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sf_ecc_data4:32; /* sf_ecc_data[151:128] */
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sf_ecc_data4:32; /* sf_ecc_data[151:128] */
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_sf_data4_t, *p_txc_sf_data4_t;
+
+#define TXC_RO_TIDS_REG (FZC_TXC + 0x200B0)
+#define TXC_RO_TIDS_OFFSET(port) (TXC_RO_TIDS_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_TIDS_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_tids_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t tids_in_use:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t tids_in_use:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_tids_t, *p_txc_ro_tids_t;
+
+#define TXC_RO_STATE0_REG (FZC_TXC + 0x200B8)
+#define TXC_RO_STATE0_OFFSET(port) (TXC_STATE0_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_STATE0_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_state0_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t duplicate_tid:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t duplicate_tid:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_state0_t, *p_txc_ro_state0_t;
+
+#define TXC_RO_STATE1_REG (FZC_TXC + 0x200C0)
+#define TXC_RO_STATE1_OFFSET(port) (TXC_STATE1_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_STATE1_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_state1_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t unused_tid:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t unused_tid:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_state1_t, *p_txc_ro_state1_t;
+
+#define TXC_RO_STATE2_REG (FZC_TXC + 0x200C8)
+#define TXC_RO_STATE2_OFFSET(port) (TXC_STATE2_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_STATE2_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_state2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t transaction_timeout:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t transaction_timeout:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_state2_t, *p_txc_ro_state2_t;
+
+#define TXC_RO_STATE3_REG (FZC_TXC + 0x200D0)
+#define TXC_RO_STATE3_OFFSET(port) (TXC_RO_STATE3_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_state3_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t enable_spacefilled_watermark:1;
+ uint32_t ro_spacefilled_watermask:10;
+ uint32_t ro_fifo_spaceavailable:10;
+ uint32_t rsv:2;
+ uint32_t enable_ro_watermark:1;
+ uint32_t highest_reorder_used:4;
+ uint32_t num_reorder_used:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t num_reorder_used:4;
+ uint32_t highest_reorder_used:4;
+ uint32_t enable_ro_watermark:1;
+ uint32_t rsv:2;
+ uint32_t ro_fifo_spaceavailable:10;
+ uint32_t ro_spacefilled_watermask:10;
+ uint32_t enable_spacefilled_watermark:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_state3_t, *p_txc_ro_state3_t;
+
+#define TXC_RO_CTL_REG (FZC_TXC + 0x200D8)
+#define TXC_RO_CTL_OFFSET(port) (TXC_RO_CTL_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+
+typedef union _txc_ro_ctl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t clr_fail_state:1;
+ uint32_t rsvd3:3;
+ uint32_t ro_addr1:4;
+ uint32_t rsvd2:1;
+ uint32_t address_failed:1;
+ uint32_t dma_failed:1;
+ uint32_t length_failed:1;
+ uint32_t rsv:1;
+ uint32_t capture_address_fail:1;
+ uint32_t capture_dma_fail:1;
+ uint32_t capture_length_fail:1;
+ uint32_t rsvd:8;
+ uint32_t ro_state_rd_done:1;
+ uint32_t ro_state_wr_done:1;
+ uint32_t ro_state_rd:1;
+ uint32_t ro_state_wr:1;
+ uint32_t ro_state_addr:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_state_addr:4;
+ uint32_t ro_state_wr:1;
+ uint32_t ro_state_rd:1;
+ uint32_t ro_state_wr_done:1;
+ uint32_t ro_state_rd_done:1;
+ uint32_t rsvd:8;
+ uint32_t capture_length_fail:1;
+ uint32_t capture_dma_fail:1;
+ uint32_t capture_address_fail:1;
+ uint32_t rsv:1;
+ uint32_t length_failed:1;
+ uint32_t dma_failed:1;
+ uint32_t address_failed:1;
+ uint32_t rsvd2:1;
+ uint32_t ro_addr1:4;
+ uint32_t rsvd3:3;
+ uint32_t clr_fail_state:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_ctl_t, *p_txc_ro_ctl_t;
+
+
+#define TXC_RO_ST_DATA0_REG (FZC_TXC + 0x200E0)
+#define TXC_RO_ST_DATA0_OFFSET(port) (TXC_RO_ST_DATA0_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_ST_DATA0_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_st_data0_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_st_dat0:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_st_dat0:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_st_data0_t, *p_txc_ro_st_data0_t;
+
+
+#define TXC_RO_ST_DATA1_REG (FZC_TXC + 0x200E8)
+#define TXC_RO_ST_DATA1_OFFSET(port) (TXC_RO_ST_DATA1_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_ST_DATA1_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_st_data1_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_st_dat1:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_st_dat1:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_st_data1_t, *p_txc_ro_st_data1_t;
+
+
+#define TXC_RO_ST_DATA2_REG (FZC_TXC + 0x200F0)
+#define TXC_RO_ST_DATA2_OFFSET(port) (TXC_RO_ST_DATA2_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_ST_DATA2_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_st_data2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_st_dat2:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_st_dat2:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_st_data2_t, *p_txc_ro_st_data2_t;
+
+#define TXC_RO_ST_DATA3_REG (FZC_TXC + 0x200F8)
+#define TXC_RO_ST_DATA3_OFFSET(port) (TXC_RO_ST_DATA3_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_RO_ST_DATA3_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_ro_st_data3_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ro_st_dat3:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ro_st_dat3:32;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_ro_st_data3_t, *p_txc_ro_st_data3_t;
+
+#define TXC_PORT_PACKET_REQ_REG (FZC_TXC + 0x20100)
+#define TXC_PORT_PACKET_REQ_OFFSET(port) (TXC_PORT_PACKET_REQ_REG + \
+ (TXC_FZC_CNTL_PORT_OFFSET(port)))
+#define TXC_PORT_PACKET_REQ_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_port_packet_req_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t gather_req:4;
+ uint32_t packet_eq:12;
+ uint32_t pkterr_abort:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkterr_abort:16;
+ uint32_t packet_eq:12;
+ uint32_t gather_req:4;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_port_packet_req_t, *p_txc_port_packet_req_t;
+
+/* Reorder error bits in interrupt registers */
+#define TXC_INT_STAT_SF_CORR_ERR 0x01
+#define TXC_INT_STAT_SF_UNCORR_ERR 0x02
+#define TXC_INT_STAT_RO_CORR_ERR 0x04
+#define TXC_INT_STAT_RO_UNCORR_ERR 0x08
+#define TXC_INT_STAT_REORDER_ERR 0x10
+#define TXC_INT_STAT_PKTASSYDEAD 0x20
+
+#define TXC_INT_STAT_DBG_REG (FZC_TXC + 0x20420)
+#define TXC_INT_STAT_DBG_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_int_stat_dbg_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd3:2;
+ uint32_t port3_int_status:6;
+ uint32_t rsvd2:2;
+ uint32_t port2_int_status:6;
+ uint32_t rsvd1:2;
+ uint32_t port1_int_status:6;
+ uint32_t rsvd:2;
+ uint32_t port0_int_status:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_int_status:6;
+ uint32_t rsvd:2;
+ uint32_t port1_int_status:6;
+ uint32_t rsvd1:2;
+ uint32_t port2_int_status:6;
+ uint32_t rsvd2:2;
+ uint32_t port3_int_status:6;
+ uint32_t rsvd3:2;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_int_stat_dbg_t, *p_txc_int_stat_dbg_t;
+
+
+#define TXC_INT_STAT_REG (FZC_TXC + 0x20428)
+#define TXC_INT_STAT_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_int_stat_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd3:2;
+ uint32_t port3_int_status:6;
+ uint32_t rsvd2:2;
+ uint32_t port2_int_status:6;
+ uint32_t rsvd1:2;
+ uint32_t port1_int_status:6;
+ uint32_t rsvd:2;
+ uint32_t port0_int_status:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_int_status:6;
+ uint32_t rsvd:2;
+ uint32_t port1_int_status:6;
+ uint32_t rsvd1:2;
+ uint32_t port2_int_status:6;
+ uint32_t rsvd2:2;
+ uint32_t port3_int_status:6;
+ uint32_t rsvd3:2;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_int_stat_t, *p_txc_int_stat_t;
+
+#define TXC_INT_MASK_REG (FZC_TXC + 0x20430)
+#define TXC_INT_MASK_MASK 0x00000000FFFFFFFFULL
+
+typedef union _txc_int_mask_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd3:2;
+ uint32_t port3_int_mask:6;
+ uint32_t rsvd2:2;
+ uint32_t port2_int_mask:6;
+ uint32_t rsvd1:2;
+ uint32_t port1_int_mask:6;
+ uint32_t rsvd:2;
+ uint32_t port0_int_mask:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_int_mask:6;
+ uint32_t rsvd:2;
+ uint32_t port1_int_mask:6;
+ uint32_t rsvd1:2;
+ uint32_t port2_int_mask:6;
+ uint32_t rsvd2:2;
+ uint32_t port3_int_mask:6;
+ uint32_t rsvd3:2;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_int_mask_t, *p_txc_int_mask_t;
+
+/* 2 ports */
+typedef union _txc_int_mask_n2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd1:18;
+ uint32_t port1_int_mask:6;
+ uint32_t rsvd:2;
+ uint32_t port0_int_mask:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t port0_int_mask:6;
+ uint32_t rsvd:2;
+ uint32_t port1_int_mask:6;
+ uint32_t rsvd1:18;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txc_int_mask_n2_t, *p_txc_int_mask_n2_t;
+
+typedef struct _txc_ro_states {
+ txc_roecc_st_t roecc;
+ txc_ro_data0_t d0;
+ txc_ro_data1_t d1;
+ txc_ro_data2_t d2;
+ txc_ro_data3_t d3;
+ txc_ro_data4_t d4;
+ txc_ro_tids_t tids;
+ txc_ro_state0_t st0;
+ txc_ro_state1_t st1;
+ txc_ro_state2_t st2;
+ txc_ro_state3_t st3;
+ txc_ro_ctl_t ctl;
+} txc_ro_states_t, *p_txc_ro_states_t;
+
+typedef struct _txc_sf_states {
+ txc_sfecc_st_t sfecc;
+ txc_sf_data0_t d0;
+ txc_sf_data1_t d1;
+ txc_sf_data2_t d2;
+ txc_sf_data3_t d3;
+ txc_sf_data4_t d4;
+} txc_sf_states_t, *p_txc_sf_states_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_TXC_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_txdma.h b/usr/src/uts/sun4v/sys/nxge/nxge_txdma.h
new file mode 100644
index 0000000000..fdd8a46b4a
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_txdma.h
@@ -0,0 +1,304 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_TXDMA_H
+#define _SYS_NXGE_NXGE_TXDMA_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/nxge/nxge_txdma_hw.h>
+#include <npi_txdma.h>
+
+#define TXDMA_PORT_BITMAP(nxgep) (nxgep->pt_config.tx_dma_map)
+
+#define TXDMA_RECLAIM_PENDING_DEFAULT 64
+#define TX_FULL_MARK 3
+
+/*
+ * Transmit load balancing definitions.
+ */
+#define NXGE_TX_LB_TCPUDP 0 /* default policy */
+#define NXGE_TX_LB_HASH 1 /* from the hint data */
+#define NXGE_TX_LB_DEST_MAC 2 /* Dest. MAC */
+
+/*
+ * Descriptor ring empty:
+ * (1) head index is equal to tail index.
+ * (2) wrapped around bits are the same.
+ * Descriptor ring full:
+ * (1) head index is equal to tail index.
+ * (2) wrapped around bits are different.
+ *
+ */
+#define TXDMA_RING_EMPTY(head, head_wrap, tail, tail_wrap) \
+ ((head == tail && head_wrap == tail_wrap) ? B_TRUE : B_FALSE)
+
+#define TXDMA_RING_FULL(head, head_wrap, tail, tail_wrap) \
+ ((head == tail && head_wrap != tail_wrap) ? B_TRUE : B_FALSE)
+
+#define TXDMA_DESC_NEXT_INDEX(index, entries, wrap_mask) \
+ ((index + entries) & wrap_mask)
+
+#define TXDMA_DRR_WEIGHT_DEFAULT 0x001f
+
+typedef struct _tx_msg_t {
+ nxge_os_block_mv_t flags; /* DMA, BCOPY, DVMA (?) */
+ nxge_os_dma_common_t buf_dma; /* premapped buffer blocks */
+ nxge_os_dma_handle_t buf_dma_handle; /* premapped buffer handle */
+ nxge_os_dma_handle_t dma_handle; /* DMA handle for normal send */
+ nxge_os_dma_handle_t dvma_handle; /* Fast DVMA handle */
+
+ p_mblk_t tx_message;
+ uint32_t tx_msg_size;
+ size_t bytes_used;
+ int head;
+ int tail;
+} tx_msg_t, *p_tx_msg_t;
+
+/*
+ * TX Statistics.
+ */
+typedef struct _nxge_tx_ring_stats_t {
+ uint64_t opackets;
+ uint64_t obytes;
+ uint64_t oerrors;
+
+ uint32_t tx_inits;
+ uint32_t tx_no_buf;
+
+ uint32_t mbox_err;
+ uint32_t pkt_size_err;
+ uint32_t tx_ring_oflow;
+ uint32_t pre_buf_par_err;
+ uint32_t nack_pref;
+ uint32_t nack_pkt_rd;
+ uint32_t conf_part_err;
+ uint32_t pkt_part_err;
+ uint32_t tx_starts;
+ uint32_t tx_nocanput;
+ uint32_t tx_msgdup_fail;
+ uint32_t tx_allocb_fail;
+ uint32_t tx_no_desc;
+ uint32_t tx_dma_bind_fail;
+ uint32_t tx_uflo;
+
+ uint32_t tx_hdr_pkts;
+ uint32_t tx_ddi_pkts;
+ uint32_t tx_dvma_pkts;
+
+ uint32_t tx_max_pend;
+ uint32_t tx_jumbo_pkts;
+
+ txdma_ring_errlog_t errlog;
+} nxge_tx_ring_stats_t, *p_nxge_tx_ring_stats_t;
+
+typedef struct _tx_ring_t {
+ nxge_os_dma_common_t tdc_desc;
+ struct _nxge_t *nxgep;
+ p_tx_msg_t tx_msg_ring;
+ uint32_t tnblocks;
+ tx_rng_cfig_t tx_ring_cfig;
+ tx_ring_hdl_t tx_ring_hdl;
+ tx_ring_kick_t tx_ring_kick;
+ tx_cs_t tx_cs;
+ tx_dma_ent_msk_t tx_evmask;
+ txdma_mbh_t tx_mbox_mbh;
+ txdma_mbl_t tx_mbox_mbl;
+ log_page_vld_t page_valid;
+ log_page_mask_t page_mask_1;
+ log_page_mask_t page_mask_2;
+ log_page_value_t page_value_1;
+ log_page_value_t page_value_2;
+ log_page_relo_t page_reloc_1;
+ log_page_relo_t page_reloc_2;
+ log_page_hdl_t page_hdl;
+ txc_dma_max_burst_t max_burst;
+ boolean_t cfg_set;
+ uint32_t tx_ring_state;
+
+ nxge_os_mutex_t lock;
+ uint16_t index;
+ uint16_t tdc;
+ struct nxge_tdc_cfg *tdc_p;
+ uint_t tx_ring_size;
+ uint32_t num_chunks;
+
+ uint_t tx_wrap_mask;
+ uint_t rd_index;
+ uint_t wr_index;
+ boolean_t wr_index_wrap;
+ uint_t head_index;
+ boolean_t head_wrap;
+ tx_ring_hdl_t ring_head;
+ tx_ring_kick_t ring_kick_tail;
+ txdma_mailbox_t tx_mbox;
+
+ uint_t descs_pending;
+ boolean_t queueing;
+
+ nxge_os_mutex_t sq_lock;
+
+ p_mblk_t head;
+ p_mblk_t tail;
+
+ uint16_t ldg_group_id;
+ p_nxge_tx_ring_stats_t tdc_stats;
+
+ nxge_os_mutex_t dvma_lock;
+ uint_t dvma_wr_index;
+ uint_t dvma_rd_index;
+ uint_t dvma_pending;
+ uint_t dvma_available;
+ uint_t dvma_wrap_mask;
+
+ nxge_os_dma_handle_t *dvma_ring;
+
+#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
+ uint64_t hv_tx_buf_base_ioaddr_pp;
+ uint64_t hv_tx_buf_ioaddr_size;
+ uint64_t hv_tx_cntl_base_ioaddr_pp;
+ uint64_t hv_tx_cntl_ioaddr_size;
+ boolean_t hv_set;
+#endif
+} tx_ring_t, *p_tx_ring_t;
+
+
+/* Transmit Mailbox */
+typedef struct _tx_mbox_t {
+ nxge_os_mutex_t lock;
+ uint16_t index;
+ struct _nxge_t *nxgep;
+ uint16_t tdc;
+ nxge_os_dma_common_t tx_mbox;
+ txdma_mbl_t tx_mbox_l;
+ txdma_mbh_t tx_mbox_h;
+} tx_mbox_t, *p_tx_mbox_t;
+
+typedef struct _tx_rings_t {
+ p_tx_ring_t *rings;
+ boolean_t txdesc_allocated;
+ uint32_t ndmas;
+ nxge_os_dma_common_t tdc_dma;
+ nxge_os_dma_common_t tdc_mbox;
+} tx_rings_t, *p_tx_rings_t;
+
+
+#if defined(_KERNEL) || (defined(COSIM) && !defined(IODIAG))
+
+typedef struct _tx_buf_rings_t {
+ struct _tx_buf_ring_t *txbuf_rings;
+ boolean_t txbuf_allocated;
+} tx_buf_rings_t, *p_tx_buf_rings_t;
+
+#endif
+
+typedef struct _tx_mbox_areas_t {
+ p_tx_mbox_t *txmbox_areas_p;
+ boolean_t txmbox_allocated;
+} tx_mbox_areas_t, *p_tx_mbox_areas_t;
+
+typedef struct _tx_param_t {
+ nxge_logical_page_t tx_logical_pages[NXGE_MAX_LOGICAL_PAGES];
+} tx_param_t, *p_tx_param_t;
+
+typedef struct _tx_params {
+ struct _tx_param_t *tx_param_p;
+} tx_params_t, *p_tx_params_t;
+
+/*
+ * Global register definitions per chip and they are initialized
+ * using the function zero control registers.
+ * .
+ */
+typedef struct _txdma_globals {
+ boolean_t mode32;
+} txdma_globals_t, *p_txdma_globals;
+
+
+#if defined(SOLARIS) && (defined(_KERNEL) || \
+ (defined(COSIM) && !defined(IODIAG)))
+
+/*
+ * Transmit prototypes.
+ */
+nxge_status_t nxge_init_txdma_channels(p_nxge_t);
+void nxge_uninit_txdma_channels(p_nxge_t);
+void nxge_setup_dma_common(p_nxge_dma_common_t, p_nxge_dma_common_t,
+ uint32_t, uint32_t);
+nxge_status_t nxge_reset_txdma_channel(p_nxge_t, uint16_t,
+ uint64_t);
+nxge_status_t nxge_init_txdma_channel_event_mask(p_nxge_t,
+ uint16_t, p_tx_dma_ent_msk_t);
+nxge_status_t nxge_init_txdma_channel_cntl_stat(p_nxge_t,
+ uint16_t, uint64_t);
+nxge_status_t nxge_enable_txdma_channel(p_nxge_t, uint16_t,
+ p_tx_ring_t, p_tx_mbox_t);
+
+p_mblk_t nxge_tx_pkt_header_reserve(p_mblk_t, uint8_t *);
+int nxge_tx_pkt_nmblocks(p_mblk_t, int *);
+boolean_t nxge_txdma_reclaim(p_nxge_t, p_tx_ring_t, int);
+
+void nxge_fill_tx_hdr(p_mblk_t, boolean_t, boolean_t,
+ int, uint8_t, p_tx_pkt_hdr_all_t);
+
+nxge_status_t nxge_txdma_hw_mode(p_nxge_t, boolean_t);
+void nxge_hw_start_tx(p_nxge_t);
+void nxge_txdma_stop(p_nxge_t);
+void nxge_txdma_stop_start(p_nxge_t);
+void nxge_fixup_txdma_rings(p_nxge_t);
+void nxge_txdma_hw_kick(p_nxge_t);
+void nxge_txdma_fix_channel(p_nxge_t, uint16_t);
+void nxge_txdma_fixup_channel(p_nxge_t, p_tx_ring_t,
+ uint16_t);
+void nxge_txdma_hw_kick_channel(p_nxge_t, p_tx_ring_t,
+ uint16_t);
+
+void nxge_txdma_regs_dump(p_nxge_t, int);
+void nxge_txdma_regs_dump_channels(p_nxge_t);
+
+void nxge_check_tx_hang(p_nxge_t);
+void nxge_fixup_hung_txdma_rings(p_nxge_t);
+void nxge_txdma_fix_hung_channel(p_nxge_t, uint16_t);
+void nxge_txdma_fixup_hung_channel(p_nxge_t, p_tx_ring_t,
+ uint16_t);
+
+void nxge_reclaim_rings(p_nxge_t);
+int nxge_txdma_channel_hung(p_nxge_t,
+ p_tx_ring_t tx_ring_p, uint16_t);
+int nxge_txdma_hung(p_nxge_t);
+int nxge_txdma_stop_inj_err(p_nxge_t, int);
+void nxge_txdma_inject_err(p_nxge_t, uint32_t, uint8_t);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_TXDMA_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_txdma_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_txdma_hw.h
new file mode 100644
index 0000000000..da234ee008
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_txdma_hw.h
@@ -0,0 +1,1031 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_TXDMA_HW_H
+#define _SYS_NXGE_NXGE_TXDMA_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+#include <nxge_hw.h>
+
+#if !defined(_BIG_ENDIAN)
+#define SWAP(X) (X)
+#else
+#define SWAP(X) \
+ (((X >> 32) & 0x00000000ffffffff) | \
+ ((X << 32) & 0xffffffff00000000))
+#endif
+
+/*
+ * Partitioning Suport: same as those defined for the RX
+ */
+/*
+ * TDC: Partitioning Support
+ * (Each of the following registers is for each TDC)
+ */
+#define TX_LOG_REG_SIZE 512
+#define TX_LOG_DMA_OFFSET(channel) (channel * TX_LOG_REG_SIZE)
+
+#define TX_LOG_PAGE_VLD_REG (FZC_DMC + 0x40000)
+#define TX_LOG_PAGE_MASK1_REG (FZC_DMC + 0x40008)
+#define TX_LOG_PAGE_VAL1_REG (FZC_DMC + 0x40010)
+#define TX_LOG_PAGE_MASK2_REG (FZC_DMC + 0x40018)
+#define TX_LOG_PAGE_VAL2_REG (FZC_DMC + 0x40020)
+#define TX_LOG_PAGE_RELO1_REG (FZC_DMC + 0x40028)
+#define TX_LOG_PAGE_RELO2_REG (FZC_DMC + 0x40030)
+#define TX_LOG_PAGE_HDL_REG (FZC_DMC + 0x40038)
+
+/* Transmit Addressing Mode: Set to 1 to select 32-bit addressing mode */
+#define TX_ADDR_MD_REG (FZC_DMC + 0x45000)
+
+#define TX_ADDR_MD_SHIFT 0 /* bits 0:0 */
+#define TX_ADDR_MD_SET_32 0x0000000000000001ULL /* 1 to select 32 bit */
+#define TX_ADDR_MD_MASK 0x0000000000000001ULL
+
+typedef union _tx_addr_md_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:31;
+ uint32_t mode32:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mode32:1;
+ uint32_t res1_1:31;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_addr_md_t, *p_tx_addr_md_t;
+
+/* Transmit Packet Descriptor Structure */
+#define TX_PKT_DESC_SAD_SHIFT 0 /* bits 43:0 */
+#define TX_PKT_DESC_SAD_MASK 0x00000FFFFFFFFFFFULL
+#define TX_PKT_DESC_TR_LEN_SHIFT 44 /* bits 56:44 */
+#define TX_PKT_DESC_TR_LEN_MASK 0x01FFF00000000000ULL
+#define TX_PKT_DESC_NUM_PTR_SHIFT 58 /* bits 61:58 */
+#define TX_PKT_DESC_NUM_PTR_MASK 0x3C00000000000000ULL
+#define TX_PKT_DESC_MARK_SHIFT 62 /* bit 62 */
+#define TX_PKT_DESC_MARK 0x4000000000000000ULL
+#define TX_PKT_DESC_MARK_MASK 0x4000000000000000ULL
+#define TX_PKT_DESC_SOP_SHIFT 63 /* bit 63 */
+#define TX_PKT_DESC_SOP 0x8000000000000000ULL
+#define TX_PKT_DESC_SOP_MASK 0x8000000000000000ULL
+
+typedef union _tx_desc_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sop:1;
+ uint32_t mark:1;
+ uint32_t num_ptr:4;
+ uint32_t res1:1;
+ uint32_t tr_len:13;
+ uint32_t sad:12;
+
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sad:12;
+ uint32_t tr_len:13;
+ uint32_t res1:1;
+ uint32_t num_ptr:4;
+ uint32_t mark:1;
+ uint32_t sop:1;
+
+#endif
+ } hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sad:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sad:32;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ struct {
+
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t sop:1;
+ uint32_t mark:1;
+ uint32_t num_ptr:4;
+ uint32_t res1:1;
+ uint32_t tr_len:13;
+ uint32_t sad:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t sad:12;
+ uint32_t tr_len:13;
+ uint32_t res1:1;
+ uint32_t num_ptr:4;
+ uint32_t mark:1;
+ uint32_t sop:1;
+#endif
+ } hdw;
+#endif
+ } bits;
+} tx_desc_t, *p_tx_desc_t;
+
+
+/* Transmit Ring Configuration (24 Channels) */
+#define TX_RNG_CFIG_REG (DMC + 0x40000)
+#if OLD
+#define TX_RING_HDH_REG (DMC + 0x40008)
+#endif
+#define TX_RING_HDL_REG (DMC + 0x40010)
+#define TX_RING_KICK_REG (DMC + 0x40018)
+#define TX_ENT_MSK_REG (DMC + 0x40020)
+#define TX_CS_REG (DMC + 0x40028)
+#define TXDMA_MBH_REG (DMC + 0x40030)
+#define TXDMA_MBL_REG (DMC + 0x40038)
+#define TX_DMA_PRE_ST_REG (DMC + 0x40040)
+#define TX_RNG_ERR_LOGH_REG (DMC + 0x40048)
+#define TX_RNG_ERR_LOGL_REG (DMC + 0x40050)
+#define TDMC_INTR_DBG_REG (DMC + 0x40060)
+#define TX_CS_DBG_REG (DMC + 0x40068)
+
+/* Transmit Ring Configuration */
+#define TX_RNG_CFIG_STADDR_SHIFT 6 /* bits 18:6 */
+#define TX_RNG_CFIG_STADDR_MASK 0x000000000007FFC0ULL
+#define TX_RNG_CFIG_ADDR_MASK 0x00000FFFFFFFFFC0ULL
+#define TX_RNG_CFIG_STADDR_BASE_SHIFT 19 /* bits 43:19 */
+#define TX_RNG_CFIG_STADDR_BASE_MASK 0x00000FFFFFF80000ULL
+#define TX_RNG_CFIG_LEN_SHIFT 48 /* bits 60:48 */
+#define TX_RNG_CFIG_LEN_MASK 0xFFF8000000000000ULL
+
+#define TX_RNG_HEAD_TAIL_SHIFT 3
+#define TX_RNG_HEAD_TAIL_WRAP_SHIFT 19
+
+typedef union _tx_rng_cfig_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2:3;
+ uint32_t len:13;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:13;
+ uint32_t res2:3;
+#endif
+ } hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t staddr_base:13;
+ uint32_t staddr:13;
+ uint32_t res2:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:6;
+ uint32_t staddr:13;
+ uint32_t staddr_base:13;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res2:3;
+ uint32_t len:13;
+ uint32_t res1:4;
+ uint32_t staddr_base:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t staddr_base:12;
+ uint32_t res1:4;
+ uint32_t len:13;
+ uint32_t res2:3;
+#endif
+ } hdw;
+#endif
+ } bits;
+} tx_rng_cfig_t, *p_tx_rng_cfig_t;
+
+/* Transmit Ring Head Low */
+#define TX_RING_HDL_SHIFT 3 /* bit 31:3 */
+#define TX_RING_HDL_MASK 0x00000000FFFFFFF8ULL
+
+typedef union _tx_ring_hdl_t {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0:12;
+ uint32_t wrap:1;
+ uint32_t head:16;
+ uint32_t res2:3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:3;
+ uint32_t head:16;
+ uint32_t wrap:1;
+ uint32_t res0:12;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_ring_hdl_t, *p_tx_ring_hdl_t;
+
+/* Transmit Ring Kick */
+#define TX_RING_KICK_TAIL_SHIFT 3 /* bit 43:3 */
+#define TX_RING_KICK_TAIL_MASK 0x000000FFFFFFFFFF8ULL
+
+typedef union _tx_ring_kick_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res0:12;
+ uint32_t wrap:1;
+ uint32_t tail:16;
+ uint32_t res2:3;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:3;
+ uint32_t tail:16;
+ uint32_t wrap:1;
+ uint32_t res0:12;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_ring_kick_t, *p_tx_ring_kick_t;
+
+/* Transmit Event Mask (DMC + 0x40020) */
+#define TX_ENT_MSK_PKT_PRT_ERR_SHIFT 0 /* bit 0: 0 to flag */
+#define TX_ENT_MSK_PKT_PRT_ERR_MASK 0x0000000000000001ULL
+#define TX_ENT_MSK_CONF_PART_ERR_SHIFT 1 /* bit 1: 0 to flag */
+#define TX_ENT_MSK_CONF_PART_ERR_MASK 0x0000000000000002ULL
+#define TX_ENT_MSK_NACK_PKT_RD_SHIFT 2 /* bit 2: 0 to flag */
+#define TX_ENT_MSK_NACK_PKT_RD_MASK 0x0000000000000004ULL
+#define TX_ENT_MSK_NACK_PREF_SHIFT 3 /* bit 3: 0 to flag */
+#define TX_ENT_MSK_NACK_PREF_MASK 0x0000000000000008ULL
+#define TX_ENT_MSK_PREF_BUF_ECC_ERR_SHIFT 4 /* bit 4: 0 to flag */
+#define TX_ENT_MSK_PREF_BUF_ECC_ERR_MASK 0x0000000000000010ULL
+#define TX_ENT_MSK_TX_RING_OFLOW_SHIFT 5 /* bit 5: 0 to flag */
+#define TX_ENT_MSK_TX_RING_OFLOW_MASK 0x0000000000000020ULL
+#define TX_ENT_MSK_PKT_SIZE_ERR_SHIFT 6 /* bit 6: 0 to flag */
+#define TX_ENT_MSK_PKT_SIZE_ERR_MASK 0x0000000000000040ULL
+#define TX_ENT_MSK_MBOX_ERR_SHIFT 7 /* bit 7: 0 to flag */
+#define TX_ENT_MSK_MBOX_ERR_MASK 0x0000000000000080ULL
+#define TX_ENT_MSK_MK_SHIFT 15 /* bit 15: 0 to flag */
+#define TX_ENT_MSK_MK_MASK 0x0000000000008000ULL
+#define TX_ENT_MSK_MK_ALL (TX_ENT_MSK_PKT_PRT_ERR_MASK | \
+ TX_ENT_MSK_CONF_PART_ERR_MASK | \
+ TX_ENT_MSK_NACK_PKT_RD_MASK | \
+ TX_ENT_MSK_NACK_PREF_MASK | \
+ TX_ENT_MSK_PREF_BUF_ECC_ERR_MASK | \
+ TX_ENT_MSK_TX_RING_OFLOW_MASK | \
+ TX_ENT_MSK_PKT_SIZE_ERR_MASK | \
+ TX_ENT_MSK_MBOX_ERR_MASK | \
+ TX_ENT_MSK_MK_MASK)
+
+
+typedef union _tx_dma_ent_msk_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:16;
+ uint32_t mk:1;
+ uint32_t res2:7;
+ uint32_t mbox_err:1;
+ uint32_t pkt_size_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pref_buf_ecc_err:1;
+ uint32_t nack_pref:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t conf_part_err:1;
+ uint32_t pkt_prt_err:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_prt_err:1;
+ uint32_t conf_part_err:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t nack_pref:1;
+ uint32_t pref_buf_ecc_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pkt_size_err:1;
+ uint32_t mbox_err:1;
+ uint32_t res2:7;
+ uint32_t mk:1;
+ uint32_t res1_1:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_dma_ent_msk_t, *p_tx_dma_ent_msk_t;
+
+
+/* Transmit Control and Status (DMC + 0x40028) */
+#define TX_CS_PKT_PRT_ERR_SHIFT 0 /* RO, bit 0 */
+#define TX_CS_PKT_PRT_ERR_MASK 0x0000000000000001ULL
+#define TX_CS_CONF_PART_ERR_SHIF 1 /* RO, bit 1 */
+#define TX_CS_CONF_PART_ERR_MASK 0x0000000000000002ULL
+#define TX_CS_NACK_PKT_RD_SHIFT 2 /* RO, bit 2 */
+#define TX_CS_NACK_PKT_RD_MASK 0x0000000000000004ULL
+#define TX_CS_PREF_SHIFT 3 /* RO, bit 3 */
+#define TX_CS_PREF_MASK 0x0000000000000008ULL
+#define TX_CS_PREF_BUF_PAR_ERR_SHIFT 4 /* RO, bit 4 */
+#define TX_CS_PREF_BUF_PAR_ERR_MASK 0x0000000000000010ULL
+#define TX_CS_RING_OFLOW_SHIFT 5 /* RO, bit 5 */
+#define TX_CS_RING_OFLOW_MASK 0x0000000000000020ULL
+#define TX_CS_PKT_SIZE_ERR_SHIFT 6 /* RW, bit 6 */
+#define TX_CS_PKT_SIZE_ERR_MASK 0x0000000000000040ULL
+#define TX_CS_MMK_SHIFT 14 /* RC, bit 14 */
+#define TX_CS_MMK_MASK 0x0000000000004000ULL
+#define TX_CS_MK_SHIFT 15 /* RCW1C, bit 15 */
+#define TX_CS_MK_MASK 0x0000000000008000ULL
+#define TX_CS_SNG_SHIFT 27 /* RO, bit 27 */
+#define TX_CS_SNG_MASK 0x0000000008000000ULL
+#define TX_CS_STOP_N_GO_SHIFT 28 /* RW, bit 28 */
+#define TX_CS_STOP_N_GO_MASK 0x0000000010000000ULL
+#define TX_CS_MB_SHIFT 29 /* RO, bit 29 */
+#define TX_CS_MB_MASK 0x0000000020000000ULL
+#define TX_CS_RST_STATE_SHIFT 30 /* Rw, bit 30 */
+#define TX_CS_RST_STATE_MASK 0x0000000040000000ULL
+#define TX_CS_RST_SHIFT 31 /* Rw, bit 31 */
+#define TX_CS_RST_MASK 0x0000000080000000ULL
+#define TX_CS_LASTMASK_SHIFT 32 /* RW, bit 43:32 */
+#define TX_CS_LASTMARK_MASK 0x00000FFF00000000ULL
+#define TX_CS_PKT_CNT_SHIFT 48 /* RW, bit 59:48 */
+#define TX_CS_PKT_CNT_MASK 0x0FFF000000000000ULL
+
+/* Trasnmit Control and Status */
+typedef union _tx_cs_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res2:4;
+ uint32_t lastmark:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t lastmark:12;
+ uint32_t res2:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res1:4;
+#endif
+ } hdw;
+
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rst:1;
+ uint32_t rst_state:1;
+ uint32_t mb:1;
+ uint32_t stop_n_go:1;
+ uint32_t sng_state:1;
+ uint32_t res1:11;
+ uint32_t mk:1;
+ uint32_t mmk:1;
+ uint32_t res2:6;
+ uint32_t mbox_err:1;
+ uint32_t pkt_size_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pref_buf_par_err:1;
+ uint32_t nack_pref:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t conf_part_err:1;
+ uint32_t pkt_prt_err:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_prt_err:1;
+ uint32_t conf_part_err:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t nack_pref:1;
+ uint32_t pref_buf_par_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pkt_size_err:1;
+ uint32_t mbox_err:1;
+ uint32_t res2:6;
+ uint32_t mmk:1;
+ uint32_t mk:1;
+ uint32_t res1:11;
+ uint32_t sng_state:1;
+ uint32_t stop_n_go:1;
+ uint32_t mb:1;
+ uint32_t rst_state:1;
+ uint32_t rst:1;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res2:4;
+ uint32_t lastmark:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t lastmark:12;
+ uint32_t res2:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res1:4;
+#endif
+ } hdw;
+
+#endif
+ } bits;
+} tx_cs_t, *p_tx_cs_t;
+
+/* Trasnmit Mailbox High (DMC + 0x40030) */
+#define TXDMA_MBH_SHIFT 0 /* bit 11:0 */
+#define TXDMA_MBH_ADDR_SHIFT 32 /* bit 43:32 */
+#define TXDMA_MBH_MASK 0x0000000000000FFFULL
+
+typedef union _txdma_mbh_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:20;
+ uint32_t mbaddr:12;
+
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mbaddr:12;
+ uint32_t res1_1:20;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txdma_mbh_t, *p_txdma_mbh_t;
+
+
+/* Trasnmit Mailbox Low (DMC + 0x40038) */
+#define TXDMA_MBL_SHIFT 6 /* bit 31:6 */
+#define TXDMA_MBL_MASK 0x00000000FFFFFFC0ULL
+
+typedef union _txdma_mbl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t mbaddr:26;
+ uint32_t res2:6;
+
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:6;
+ uint32_t mbaddr:26;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txdma_mbl_t, *p_txdma_mbl_t;
+
+/* Trasnmit Prefetch State High (DMC + 0x40040) */
+#define TX_DMA_PREF_ST_SHIFT 0 /* bit 5:0 */
+#define TX_DMA_PREF_ST_MASK 0x000000000000003FULL
+
+typedef union _tx_dma_pre_st_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:13;
+ uint32_t shadow_hd:19;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t shadow_hd:19;
+ uint32_t res1_1:13;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_dma_pre_st_t, *p_tx_dma_pre_st_t;
+
+/* Trasnmit Ring Error Log High (DMC + 0x40048) */
+#define TX_RNG_ERR_LOGH_ERR_ADDR_SHIFT 0 /* RO bit 11:0 */
+#define TX_RNG_ERR_LOGH_ERR_ADDR_MASK 0x0000000000000FFFULL
+#define TX_RNG_ERR_LOGH_ADDR_SHIFT 32
+#define TX_RNG_ERR_LOGH_ERRCODE_SHIFT 26 /* RO bit 29:26 */
+#define TX_RNG_ERR_LOGH_ERRCODE_MASK 0x000000003C000000ULL
+#define TX_RNG_ERR_LOGH_MERR_SHIFT 30 /* RO bit 30 */
+#define TX_RNG_ERR_LOGH_MERR_MASK 0x0000000040000000ULL
+#define TX_RNG_ERR_LOGH_ERR_SHIFT 31 /* RO bit 31 */
+#define TX_RNG_ERR_LOGH_ERR_MASK 0x0000000080000000ULL
+
+/* Transmit Ring Error codes */
+#define TXDMA_RING_PKT_PRT_ERR 0
+#define TXDMA_RING_CONF_PART_ERR 0x01
+#define TXDMA_RING_NACK_PKT_ERR 0x02
+#define TXDMA_RING_NACK_PREF_ERR 0x03
+#define TXDMA_RING_PREF_BUF_PAR_ERR 0x04
+#define TXDMA_RING_TX_RING_OFLOW_ERR 0x05
+#define TXDMA_RING_PKT_SIZE_ERR 0x06
+
+typedef union _tx_rng_err_logh_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t err:1;
+ uint32_t merr:1;
+ uint32_t errcode:4;
+ uint32_t res2:14;
+ uint32_t err_addr:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t err_addr:12;
+ uint32_t res2:14;
+ uint32_t errcode:4;
+ uint32_t merr:1;
+ uint32_t err:1;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_rng_err_logh_t, *p_tx_rng_err_logh_t;
+
+
+/* Trasnmit Ring Error Log Log (DMC + 0x40050) */
+#define TX_RNG_ERR_LOGL_ERR_ADDR_SHIFT 0 /* RO bit 31:0 */
+#define TX_RNG_ERR_LOGL_ERR_ADDR_MASK 0x00000000FFFFFFFFULL
+
+typedef union _tx_rng_err_logl_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t err_addr:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t err_addr:32;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_rng_err_logl_t, *p_tx_rng_err_logl_t;
+
+/*
+ * TDMC_INTR_RBG_REG (DMC + 0x40060)
+ */
+typedef union _tdmc_intr_dbg_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res:16;
+ uint32_t mk:1;
+ uint32_t rsvd:7;
+ uint32_t mbox_err:1;
+ uint32_t pkt_size_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pref_buf_par_err:1;
+ uint32_t nack_pref:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t conf_part_err:1;
+ uint32_t pkt_part_err:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pkt_part_err:1;
+ uint32_t conf_part_err:1;
+ uint32_t nack_pkt_rd:1;
+ uint32_t nack_pref:1;
+ uint32_t pref_buf_par_err:1;
+ uint32_t tx_ring_oflow:1;
+ uint32_t pkt_size_err:1;
+ uint32_t mbox_err:1;
+ uint32_t rsvd:7;
+ uint32_t mk:1;
+ uint32_t res:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tdmc_intr_dbg_t, *p_tdmc_intr_dbg_t;
+
+
+/*
+ * TX_CS_DBG (DMC + 0x40068)
+ */
+typedef union _tx_cs_dbg_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res2:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:16;
+ uint32_t pkt_cnt:12;
+ uint32_t res1:4;
+#endif
+ } hdw;
+
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rsvd:32;
+
+#endif
+ } ldw;
+
+#ifndef _BIG_ENDIAN
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1:4;
+ uint32_t pkt_cnt:12;
+ uint32_t res2:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t res2:16;
+ uint32_t pkt_cnt:12;
+ uint32_t res1:4;
+#endif
+ } hdw;
+
+#endif
+ } bits;
+} tx_cs_dbg_t, *p_tx_cs_dbg_t;
+
+#define TXDMA_MAILBOX_BYTE_LENGTH 64
+#define TXDMA_MAILBOX_UNUSED 24
+
+typedef struct _txdma_mailbox_t {
+ tx_cs_t tx_cs; /* 8 bytes */
+ tx_dma_pre_st_t tx_dma_pre_st; /* 8 bytes */
+ tx_ring_hdl_t tx_ring_hdl; /* 8 bytes */
+ tx_ring_kick_t tx_ring_kick; /* 8 bytes */
+ uint32_t tx_rng_err_logh; /* 4 bytes */
+ uint32_t tx_rng_err_logl; /* 4 bytes */
+ uint32_t resv[TXDMA_MAILBOX_UNUSED];
+} txdma_mailbox_t, *p_txdma_mailbox_t;
+
+#if OLD
+/* Transmit Ring Scheduler (per port) */
+#define TX_DMA_MAP_OFFSET(port) (port * 8 + TX_DMA_MAP_REG)
+#define TX_DMA_MAP_PORT_OFFSET(port) (port * 8)
+#define TX_DMA_MAP_REG (FZC_DMC + 0x50000)
+#define TX_DMA_MAP0_REG (FZC_DMC + 0x50000)
+#define TX_DMA_MAP1_REG (FZC_DMC + 0x50008)
+#define TX_DMA_MAP2_REG (FZC_DMC + 0x50010)
+#define TX_DMA_MAP3_REG (FZC_DMC + 0x50018)
+
+#define TX_DMA_MAP_SHIFT 0 /* RO bit 31:0 */
+#define TX_DMA_MAPMASK 0x00000000FFFFFFFFULL
+
+typedef union _tx_dma_map_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t bind:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t bind:32;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tx_dma_map_t, *p_tx_dma_map_t;
+#endif
+
+#if OLD
+/* Transmit Ring Scheduler: DRR Weight (32 Channels) */
+#define DRR_WT_REG (FZC_DMC + 0x51000)
+#define DRR_WT_SHIFT 0 /* RO bit 19:0 */
+#define DRR_WT_MASK 0x00000000000FFFFFULL
+
+#define TXDMA_DRR_RNG_USE_OFFSET(channel) (channel * 16)
+
+typedef union _drr_wt_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:12;
+ uint32_t wt:20;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t wt:20;
+ uint32_t res1_1:12;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} drr_wt_t, *p_drr_wt_t;
+#endif
+
+#if OLD
+
+/* Performance Monitoring (32 Channels) */
+#define TXRNG_USE_REG (FZC_DMC + 0x51008)
+#define TXRNG_USE_CNT_SHIFT 0 /* RO bit 26:0 */
+#define TXRNG_USE_CNT_MASK 0x0000000007FFFFFFULL
+#define TXRNG_USE_OFLOW_SHIFT 0 /* RO bit 27 */
+#define TXRNG_USE_OFLOW_MASK 0x0000000008000000ULL
+
+typedef union _txrng_use_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t res1_1:4;
+ uint32_t oflow:1;
+ uint32_t cnt:27;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cnt:27;
+ uint32_t oflow:1;
+ uint32_t res1_1:4;
+
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} txrng_use_t, *p_txrng_use_t;
+
+#endif
+
+/*
+ * Internal Transmit Packet Format (16 bytes)
+ */
+#define TX_PKT_HEADER_SIZE 16
+#define TX_MAX_GATHER_POINTERS 15
+#define TX_GATHER_POINTERS_THRESHOLD 8
+/*
+ * There is bugs in the hardware
+ * and max sfter len is changed from 4096 to 4076.
+ *
+ * Jumbo from 9500 to 9216
+ */
+#define TX_MAX_TRANSFER_LENGTH 4076
+#define TX_JUMBO_MTU 9216
+
+#define TX_PKT_HEADER_PAD_SHIFT 0 /* bit 2:0 */
+#define TX_PKT_HEADER_PAD_MASK 0x0000000000000007ULL
+#define TX_PKT_HEADER_TOT_XFER_LEN_SHIFT 16 /* bit 16:29 */
+#define TX_PKT_HEADER_TOT_XFER_LEN_MASK 0x000000000000FFF8ULL
+#define TX_PKT_HEADER_L4STUFF_SHIFT 32 /* bit 37:32 */
+#define TX_PKT_HEADER_L4STUFF_MASK 0x0000003F00000000ULL
+#define TX_PKT_HEADER_L4START_SHIFT 40 /* bit 45:40 */
+#define TX_PKT_HEADER_L4START_MASK 0x00003F0000000000ULL
+#define TX_PKT_HEADER_L3START_SHIFT 48 /* bit 45:40 */
+#define TX_PKT_HEADER_IHL_SHIFT 52 /* bit 52 */
+#define TX_PKT_HEADER_VLAN__SHIFT 56 /* bit 56 */
+#define TX_PKT_HEADER_TCP_UDP_CRC32C_SHIFT 57 /* bit 57 */
+#define TX_PKT_HEADER_LLC_SHIFT 57 /* bit 57 */
+#define TX_PKT_HEADER_TCP_UDP_CRC32C_SET 0x0200000000000000ULL
+#define TX_PKT_HEADER_TCP_UDP_CRC32C_MASK 0x0200000000000000ULL
+#define TX_PKT_HEADER_L4_PROTO_OP_SHIFT 2 /* bit 59:58 */
+#define TX_PKT_HEADER_L4_PROTO_OP_MASK 0x0C00000000000000ULL
+#define TX_PKT_HEADER_V4_HDR_CS_SHIFT 60 /* bit 60 */
+#define TX_PKT_HEADER_V4_HDR_CS_SET 0x1000000000000000ULL
+#define TX_PKT_HEADER_V4_HDR_CS_MASK 0x1000000000000000ULL
+#define TX_PKT_HEADER_IP_VER_SHIFT 61 /* bit 61 */
+#define TX_PKT_HEADER_IP_VER_MASK 0x2000000000000000ULL
+#define TX_PKT_HEADER_PKT_TYPE_SHIFT 62 /* bit 62 */
+#define TX_PKT_HEADER_PKT_TYPE_MASK 0x4000000000000000ULL
+
+/* L4 Prototol Operations */
+#define TX_PKT_L4_PROTO_OP_NOP 0x00
+#define TX_PKT_L4_PROTO_OP_FULL_L4_CSUM 0x01
+#define TX_PKT_L4_PROTO_OP_L4_PAYLOAD_CSUM 0x02
+#define TX_PKT_L4_PROTO_OP_SCTP_CRC32 0x04
+
+/* Transmit Packet Types */
+#define TX_PKT_PKT_TYPE_NOP 0x00
+#define TX_PKT_PKT_TYPE_TCP 0x01
+#define TX_PKT_PKT_TYPE_UDP 0x02
+#define TX_PKT_PKT_TYPE_SCTP 0x03
+
+typedef union _tx_pkt_header_t {
+ uint64_t value;
+ struct {
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t pad:3;
+ uint32_t resv2:13;
+ uint32_t tot_xfer_len:14;
+ uint32_t resv1:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t pad:3;
+ uint32_t resv2:13;
+ uint32_t tot_xfer_len:14;
+ uint32_t resv1:2;
+#endif
+ } ldw;
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t l4stuff:6;
+ uint32_t resv3:2;
+ uint32_t l4start:6;
+ uint32_t resv2:2;
+ uint32_t l3start:4;
+ uint32_t ihl:4;
+ uint32_t vlan:1;
+ uint32_t llc:1;
+ uint32_t res1:3;
+ uint32_t ip_ver:1;
+ uint32_t cksum_en_pkt_type:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t l4stuff:6;
+ uint32_t resv3:2;
+ uint32_t l4start:6;
+ uint32_t resv2:2;
+ uint32_t l3start:4;
+ uint32_t ihl:4;
+ uint32_t vlan:1;
+ uint32_t llc:1;
+ uint32_t res1:3;
+ uint32_t ip_ver:1;
+ uint32_t cksum_en_pkt_type:2;
+#endif
+ } hdw;
+ } bits;
+} tx_pkt_header_t, *p_tx_pkt_header_t;
+
+typedef struct _tx_pkt_hdr_all_t {
+ tx_pkt_header_t pkthdr;
+ uint64_t reserved;
+} tx_pkt_hdr_all_t, *p_tx_pkt_hdr_all_t;
+
+/* Debug only registers */
+#define TDMC_INJ_PAR_ERR_REG (FZC_DMC + 0x45040)
+#define TDMC_INJ_PAR_ERR_MASK 0x0000000000FFFFFFULL
+#define TDMC_INJ_PAR_ERR_MASK_N2 0x000000000000FFFFULL
+
+typedef union _tdmc_inj_par_err_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvc:8;
+ uint32_t inject_parity_error:24;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t inject_parity_error:24;
+ uint32_t rsvc:8;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tdmc_inj_par_err_t, *p_tdmc_inj_par_err_t;
+
+typedef union _tdmc_inj_par_err_n2_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvc:16;
+ uint32_t inject_parity_error:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t inject_parity_error:16;
+ uint32_t rsvc:16;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tdmc_inj_par_err_n2_t, *p_tdmc_inj_par_err_n2_t;
+
+#define TDMC_DBG_SEL_REG (FZC_DMC + 0x45080)
+#define TDMC_DBG_SEL_MASK 0x000000000000003FULL
+
+typedef union _tdmc_dbg_sel_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvc:26;
+ uint32_t dbg_sel:6;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dbg_sel:6;
+ uint32_t rsvc:26;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tdmc_dbg_sel_t, *p_tdmc_dbg_sel_t;
+
+#define TDMC_TRAINING_REG (FZC_DMC + 0x45088)
+#define TDMC_TRAINING_MASK 0x00000000FFFFFFFFULL
+
+typedef union _tdmc_training_t {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t vec:32;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t vec:6;
+#endif
+ } ldw;
+#ifndef _BIG_ENDIAN
+ uint32_t hdw;
+#endif
+ } bits;
+} tdmc_training_t, *p_tdmc_training_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_TXDMA_HW_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_virtual.h b/usr/src/uts/sun4v/sys/nxge/nxge_virtual.h
new file mode 100644
index 0000000000..7006ebd443
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_virtual.h
@@ -0,0 +1,80 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_VIRTUAL_H
+#define _SYS_NXGE_NXGE_VIRTUAL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Neptune Virtualization Control Operations
+ */
+typedef enum {
+ NXGE_CTLOPS_NIUTYPE,
+ NXGE_CTLOPS_GET_ATTRIBUTES,
+ NXGE_CTLOPS_GET_HWPROPERTIES,
+ NXGE_CTLOPS_SET_HWPROPERTIES,
+ NXGE_CTLOPS_GET_SHARED_REG,
+ NXGE_CTLOPS_SET_SHARED_REG,
+ NXGE_CTLOPS_UPDATE_SHARED_REG,
+ NXGE_CTLOPS_GET_LOCK_BLOCK,
+ NXGE_CTLOPS_GET_LOCK_TRY,
+ NXGE_CTLOPS_FREE_LOCK,
+ NXGE_CTLOPS_SET_SHARED_REG_LOCK,
+ NXGE_CTLOPS_CLEAR_BIT_SHARED_REG,
+ NXGE_CTLOPS_CLEAR_BIT_SHARED_REG_UL,
+ NXGE_CTLOPS_END
+} nxge_ctl_enum_t;
+
+/* 12 bits are available */
+#define COMMON_CFG_VALID 0x01
+#define COMMON_CFG_BUSY 0x02
+#define COMMON_INIT_START 0x04
+#define COMMON_INIT_DONE 0x08
+#define COMMON_TCAM_BUSY 0x10
+#define COMMON_VLAN_BUSY 0x20
+
+#define NXGE_SR_FUNC_BUSY_SHIFT 0x8
+#define NXGE_SR_FUNC_BUSY_MASK 0xf00
+
+
+#define COMMON_TXDMA_CFG 1
+#define COMMON_RXDMA_CFG 2
+#define COMMON_RXDMA_GRP_CFG 4
+#define COMMON_CLASS_CFG 8
+#define COMMON_QUICK_CFG 0x10
+
+nxge_status_t nxge_intr_mask_mgmt(p_nxge_t nxgep);
+void nxge_virint_regs_dump(p_nxge_t nxgep);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_VIRTUAL_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_zcp.h b/usr/src/uts/sun4v/sys/nxge/nxge_zcp.h
new file mode 100644
index 0000000000..05356e628e
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_zcp.h
@@ -0,0 +1,75 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_ZCP_H
+#define _SYS_NXGE_NXGE_ZCP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_zcp_hw.h>
+#include <npi_zcp.h>
+
+typedef struct _zcp_errlog {
+ zcp_state_machine_t state_mach;
+} zcp_errlog_t, *p_zcp_errlog_t;
+
+typedef struct _nxge_zcp_stats_t {
+ uint32_t errors;
+ uint32_t inits;
+ uint32_t rrfifo_underrun;
+ uint32_t rrfifo_overrun;
+ uint32_t rspfifo_uncorr_err;
+ uint32_t buffer_overflow;
+ uint32_t stat_tbl_perr;
+ uint32_t dyn_tbl_perr;
+ uint32_t buf_tbl_perr;
+ uint32_t tt_program_err;
+ uint32_t rsp_tt_index_err;
+ uint32_t slv_tt_index_err;
+ uint32_t zcp_tt_index_err;
+ uint32_t zcp_access_fail;
+ uint32_t cfifo_ecc;
+ zcp_errlog_t errlog;
+} nxge_zcp_stats_t, *p_nxge_zcp_stats_t;
+
+typedef struct _nxge_zcp {
+ uint32_t config;
+ uint32_t iconfig;
+ nxge_zcp_stats_t *stat;
+} nxge_zcp_t;
+
+nxge_status_t nxge_zcp_init(p_nxge_t nxgep);
+void nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t);
+nxge_status_t nxge_zcp_fatal_err_recover(p_nxge_t nxgep);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_ZCP_H */
diff --git a/usr/src/uts/sun4v/sys/nxge/nxge_zcp_hw.h b/usr/src/uts/sun4v/sys/nxge/nxge_zcp_hw.h
new file mode 100644
index 0000000000..ea4a7593f6
--- /dev/null
+++ b/usr/src/uts/sun4v/sys/nxge/nxge_zcp_hw.h
@@ -0,0 +1,771 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_NXGE_NXGE_ZCP_HW_H
+#define _SYS_NXGE_NXGE_ZCP_HW_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxge_defs.h>
+
+/*
+ * Neptune Zerocopy Hardware definitions
+ * Updated to reflect PRM-0.8.
+ */
+
+#define ZCP_CONFIG_REG (FZC_ZCP + 0x00000)
+#define ZCP_INT_STAT_REG (FZC_ZCP + 0x00008)
+#define ZCP_INT_STAT_TEST_REG (FZC_ZCP + 0x00108)
+#define ZCP_INT_MASK_REG (FZC_ZCP + 0x00010)
+
+#define ZCP_BAM4_RE_CTL_REG (FZC_ZCP + 0x00018)
+#define ZCP_BAM8_RE_CTL_REG (FZC_ZCP + 0x00020)
+#define ZCP_BAM16_RE_CTL_REG (FZC_ZCP + 0x00028)
+#define ZCP_BAM32_RE_CTL_REG (FZC_ZCP + 0x00030)
+
+#define ZCP_DST4_RE_CTL_REG (FZC_ZCP + 0x00038)
+#define ZCP_DST8_RE_CTL_REG (FZC_ZCP + 0x00040)
+#define ZCP_DST16_RE_CTL_REG (FZC_ZCP + 0x00048)
+#define ZCP_DST32_RE_CTL_REG (FZC_ZCP + 0x00050)
+
+#define ZCP_RAM_DATA_REG (FZC_ZCP + 0x00058)
+#define ZCP_RAM_DATA0_REG (FZC_ZCP + 0x00058)
+#define ZCP_RAM_DATA1_REG (FZC_ZCP + 0x00060)
+#define ZCP_RAM_DATA2_REG (FZC_ZCP + 0x00068)
+#define ZCP_RAM_DATA3_REG (FZC_ZCP + 0x00070)
+#define ZCP_RAM_DATA4_REG (FZC_ZCP + 0x00078)
+#define ZCP_RAM_BE_REG (FZC_ZCP + 0x00080)
+#define ZCP_RAM_ACC_REG (FZC_ZCP + 0x00088)
+
+#define ZCP_TRAINING_VECTOR_REG (FZC_ZCP + 0x000C0)
+#define ZCP_STATE_MACHINE_REG (FZC_ZCP + 0x000C8)
+#define ZCP_CHK_BIT_DATA_REG (FZC_ZCP + 0x00090)
+#define ZCP_RESET_CFIFO_REG (FZC_ZCP + 0x00098)
+#define ZCP_RESET_CFIFO_MASK 0x0F
+
+#define ZCP_CFIFIO_RESET_WAIT 10
+#define ZCP_P0_P1_CFIFO_DEPTH 2048
+#define ZCP_P2_P3_CFIFO_DEPTH 1024
+#define ZCP_NIU_CFIFO_DEPTH 1024
+
+typedef union _zcp_reset_cfifo {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsrvd:28;
+ uint32_t reset_cfifo3:1;
+ uint32_t reset_cfifo2:1;
+ uint32_t reset_cfifo1:1;
+ uint32_t reset_cfifo0:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t reset_cfifo0:1;
+ uint32_t reset_cfifo1:1;
+ uint32_t reset_cfifo2:1;
+ uint32_t reset_cfifo3:1;
+ uint32_t rsrvd:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_reset_cfifo_t, *p_zcp_reset_cfifo_t;
+
+#define ZCP_CFIFO_ECC_PORT0_REG (FZC_ZCP + 0x000A0)
+#define ZCP_CFIFO_ECC_PORT1_REG (FZC_ZCP + 0x000A8)
+#define ZCP_CFIFO_ECC_PORT2_REG (FZC_ZCP + 0x000B0)
+#define ZCP_CFIFO_ECC_PORT3_REG (FZC_ZCP + 0x000B8)
+
+/* NOTE: Same as RX_LOG_PAGE_HDL */
+#define ZCP_PAGE_HDL_REG (FZC_DMC + 0x20038)
+
+/* Data Structures */
+
+typedef union zcp_config_reg_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:7;
+ uint32_t mode_32_bit:1;
+ uint32_t debug_sel:8;
+ uint32_t rdma_th:11;
+ uint32_t ecc_chk_dis:1;
+ uint32_t par_chk_dis:1;
+ uint32_t dis_buf_rn:1;
+ uint32_t dis_buf_rq_if:1;
+ uint32_t zc_enable:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t zc_enable:1;
+ uint32_t dis_buf_rq_if:1;
+ uint32_t dis_buf_rn:1;
+ uint32_t par_chk_dis:1;
+ uint32_t ecc_chk_dis:1;
+ uint32_t rdma_th:11;
+ uint32_t debug_sel:8;
+ uint32_t mode_32_bit:1;
+ uint32_t rsvd:7;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_config_reg_t, *zcp_config_reg_pt;
+
+#define ZCP_DEBUG_SEL_BITS 0xFF
+#define ZCP_DEBUG_SEL_SHIFT 16
+#define ZCP_DEBUG_SEL_MASK (ZCP_DEBUG_SEL_BITS << ZCP_DEBUG_SEL_SHIFT)
+#define RDMA_TH_BITS 0x7FF
+#define RDMA_TH_SHIFT 5
+#define RDMA_TH_MASK (RDMA_TH_BITS << RDMA_TH_SHIFT)
+#define ECC_CHK_DIS (1 << 4)
+#define PAR_CHK_DIS (1 << 3)
+#define DIS_BUFF_RN (1 << 2)
+#define DIS_BUFF_RQ_IF (1 << 1)
+#define ZC_ENABLE (1 << 0)
+
+typedef union zcp_int_stat_reg_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:16;
+ uint32_t rrfifo_urun:1;
+ uint32_t rrfifo_orun:1;
+ uint32_t rsvd1:1;
+ uint32_t rspfifo_uc_err:1;
+ uint32_t buf_overflow:1;
+ uint32_t stat_tbl_perr:1;
+ uint32_t dyn_tbl_perr:1;
+ uint32_t buf_tbl_perr:1;
+ uint32_t tt_tbl_perr:1;
+ uint32_t rsp_tt_index_err:1;
+ uint32_t slv_tt_index_err:1;
+ uint32_t zcp_tt_index_err:1;
+ uint32_t cfifo_ecc3:1;
+ uint32_t cfifo_ecc2:1;
+ uint32_t cfifo_ecc1:1;
+ uint32_t cfifo_ecc0:1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cfifo_ecc0:1;
+ uint32_t cfifo_ecc1:1;
+ uint32_t cfifo_ecc2:1;
+ uint32_t cfifo_ecc3:1;
+ uint32_t zcp_tt_index_err:1;
+ uint32_t slv_tt_index_err:1;
+ uint32_t rsp_tt_index_err:1;
+ uint32_t tt_tbl_perr:1;
+ uint32_t buf_tbl_perr:1;
+ uint32_t dyn_tbl_perr:1;
+ uint32_t stat_tbl_perr:1;
+ uint32_t buf_overflow:1;
+ uint32_t rspfifo_uc_err:1;
+ uint32_t rsvd1:1;
+ uint32_t rrfifo_orun:1;
+ uint32_t rrfifo_urun:1;
+ uint32_t rsvd:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_int_stat_reg_t, *zcp_int_stat_reg_pt, zcp_int_mask_reg_t,
+ *zcp_int_mask_reg_pt;
+
+#define RRFIFO_UNDERRUN (1 << 15)
+#define RRFIFO_OVERRUN (1 << 14)
+#define RSPFIFO_UNCORR_ERR (1 << 12)
+#define BUFFER_OVERFLOW (1 << 11)
+#define STAT_TBL_PERR (1 << 10)
+#define BUF_DYN_TBL_PERR (1 << 9)
+#define BUF_TBL_PERR (1 << 8)
+#define TT_PROGRAM_ERR (1 << 7)
+#define RSP_TT_INDEX_ERR (1 << 6)
+#define SLV_TT_INDEX_ERR (1 << 5)
+#define ZCP_TT_INDEX_ERR (1 << 4)
+#define CFIFO_ECC3 (1 << 3)
+#define CFIFO_ECC0 (1 << 0)
+#define CFIFO_ECC2 (1 << 2)
+#define CFIFO_ECC1 (1 << 1)
+
+typedef union zcp_bam_region_reg_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t loj:1;
+ uint32_t range_chk_en:1;
+ uint32_t last_zcfid:10;
+ uint32_t first_zcfid:10;
+ uint32_t offset:10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t offset:10;
+ uint32_t first_zcfid:10;
+ uint32_t last_zcfid:10;
+ uint32_t range_chk_en:1;
+ uint32_t loj:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_bam_region_reg_t, *zcp_bam_region_reg_pt;
+
+typedef union zcp_dst_region_reg_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:22;
+ uint32_t ds_offset:10;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rsvd:22;
+ uint32_t ds_offset:10;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_dst_region_reg_t, *zcp_dst_region_reg_pt;
+
+typedef enum tbuf_size_e {
+ TBUF_4K = 0,
+ TBUF_8K,
+ TBUF_16K,
+ TBUF_32K,
+ TBUF_64K,
+ TBUF_128K,
+ TBUF_256K,
+ TBUF_512K,
+ TBUF_1M,
+ TBUF_2M,
+ TBUF_4M,
+ TBUF_8M
+} tbuf_size_t;
+
+typedef enum tbuf_num_e {
+ TBUF_NUM_4 = 0,
+ TBUF_NUM_8,
+ TBUF_NUM_16,
+ TBUF_NUM_32
+} tbuf_num_t;
+
+typedef enum tmode_e {
+ TMODE_BASIC = 0,
+ TMODE_AUTO_UNMAP = 1,
+ TMODE_AUTO_ADV = 3
+} tmode_t;
+
+typedef struct tte_sflow_attr_s {
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ulp_end:18;
+ uint32_t num_buf:2;
+ uint32_t buf_size:4;
+ uint32_t rdc_tbl_offset:8;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t rdc_tbl_offset:8;
+ uint32_t buf_size:4;
+ uint32_t num_buf:2;
+ uint32_t ulp_end:18;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw0;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ring_base:12;
+ uint32_t skip:1;
+ uint32_t rsvd:1;
+ uint32_t tmode:2;
+ uint32_t unmap_all_en:1;
+ uint32_t ulp_end_en:1;
+ uint32_t ulp_end:14;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ulp_end:14;
+ uint32_t ulp_end_en:1;
+ uint32_t unmap_all_en:1;
+ uint32_t tmode:2;
+ uint32_t rsvd:1;
+ uint32_t skip:1;
+ uint32_t ring_base:12;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw1;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t busy:1;
+ uint32_t ring_size:4;
+ uint32_t ring_base:27;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t ring_base:27;
+ uint32_t ring_size:4;
+ uint32_t busy:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw2;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:16;
+ uint32_t toq:16;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t toq:16;
+ uint32_t rsvd:16;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw3;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:28;
+ uint32_t dat4:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dat4:4;
+ uint32_t rsvd:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw4;
+
+} tte_sflow_attr_t, *tte_sflow_attr_pt;
+
+#define TTE_RDC_TBL_SFLOW_BITS_EN 0x0001
+#define TTE_BUF_SIZE_BITS_EN 0x0002
+#define TTE_NUM_BUF_BITS_EN 0x0002
+#define TTE_ULP_END_BITS_EN 0x003E
+#define TTE_ULP_END_EN_BITS_EN 0x0020
+#define TTE_UNMAP_ALL_BITS_EN 0x0020
+#define TTE_TMODE_BITS_EN 0x0040
+#define TTE_SKIP_BITS_EN 0x0040
+#define TTE_RING_BASE_ADDR_BITS_EN 0x0FC0
+#define TTE_RING_SIZE_BITS_EN 0x0800
+#define TTE_BUSY_BITS_EN 0x0800
+#define TTE_TOQ_BITS_EN 0x3000
+
+#define TTE_MAPPED_IN_BITS_EN 0x0000F
+#define TTE_ANCHOR_SEQ_BITS_EN 0x000F0
+#define TTE_ANCHOR_OFFSET_BITS_EN 0x00700
+#define TTE_ANCHOR_BUFFER_BITS_EN 0x00800
+#define TTE_ANCHOR_BUF_FLAG_BITS_EN 0x00800
+#define TTE_UNMAP_ON_LEFT_BITS_EN 0x00800
+#define TTE_ULP_END_REACHED_BITS_EN 0x00800
+#define TTE_ERR_STAT_BITS_EN 0x01000
+#define TTE_WR_PTR_BITS_EN 0x01000
+#define TTE_HOQ_BITS_EN 0x0E000
+#define TTE_PREFETCH_ON_BITS_EN 0x08000
+
+typedef enum tring_size_e {
+ TRING_SIZE_8 = 0,
+ TRING_SIZE_16,
+ TRING_SIZE_32,
+ TRING_SIZE_64,
+ TRING_SIZE_128,
+ TRING_SIZE_256,
+ TRING_SIZE_512,
+ TRING_SIZE_1K,
+ TRING_SIZE_2K,
+ TRING_SIZE_4K,
+ TRING_SIZE_8K,
+ TRING_SIZE_16K,
+ TRING_SIZE_32K
+} tring_size_t;
+
+typedef struct tte_dflow_attr_s {
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t mapped_in;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t mapped_in;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw0;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t anchor_seq;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t anchor_seq;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw1;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t ulp_end_reached;
+ uint32_t unmap_on_left;
+ uint32_t anchor_buf_flag;
+ uint32_t anchor_buf:5;
+ uint32_t anchor_offset:24;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t anchor_offset:24;
+ uint32_t anchor_buf:5;
+ uint32_t anchor_buf_flag;
+ uint32_t unmap_on_left;
+ uint32_t ulp_end_reached;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw2;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd1:1;
+ uint32_t prefetch_on:1;
+ uint32_t hoq:16;
+ uint32_t rsvd:6;
+ uint32_t wr_ptr:6;
+ uint32_t err_stat:2;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t err_stat:2;
+ uint32_t wr_ptr:6;
+ uint32_t rsvd:6;
+ uint32_t hoq:16;
+ uint32_t prefetch_on:1;
+ uint32_t rsvd1:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw3;
+
+ union {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:28;
+ uint32_t dat4:4;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t dat4:4;
+ uint32_t rsvd:28;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+ } qw4;
+
+} tte_dflow_attr_t, *tte_dflow_attr_pt;
+
+#define MAX_BAM_BANKS 8
+
+typedef struct zcp_ram_unit_s {
+ uint32_t w0;
+ uint32_t w1;
+ uint32_t w2;
+ uint32_t w3;
+ uint32_t w4;
+} zcp_ram_unit_t;
+
+typedef enum dmaw_type_e {
+ DMAW_NO_CROSS_BUF = 0,
+ DMAW_IP_CROSS_BUF_2,
+ DMAW_IP_CROSS_BUF_3,
+ DMAW_IP_CROSS_BUF_4
+} dmaw_type_t;
+
+typedef union zcp_ram_data_u {
+ tte_sflow_attr_t sentry;
+ tte_dflow_attr_t dentry;
+} zcp_ram_data_t, *zcp_ram_data_pt;
+
+typedef union zcp_ram_access_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t busy:1;
+ uint32_t rdwr:1;
+ uint32_t rsvd:1;
+ uint32_t zcfid:12;
+ uint32_t ram_sel:5;
+ uint32_t cfifo:12;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cfifo:12;
+ uint32_t ram_sel:5;
+ uint32_t zcfid:12;
+ uint32_t rsvd:1;
+ uint32_t rdwr:1;
+ uint32_t busy:1;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_ram_access_t, *zcp_ram_access_pt;
+
+#define ZCP_RAM_WR 0
+#define ZCP_RAM_RD 1
+#define ZCP_RAM_SEL_BAM0 0
+#define ZCP_RAM_SEL_BAM1 0x1
+#define ZCP_RAM_SEL_BAM2 0x2
+#define ZCP_RAM_SEL_BAM3 0x3
+#define ZCP_RAM_SEL_BAM4 0x4
+#define ZCP_RAM_SEL_BAM5 0x5
+#define ZCP_RAM_SEL_BAM6 0x6
+#define ZCP_RAM_SEL_BAM7 0x7
+#define ZCP_RAM_SEL_TT_STATIC 0x8
+#define ZCP_RAM_SEL_TT_DYNAMIC 0x9
+#define ZCP_RAM_SEL_CFIFO0 0x10
+#define ZCP_RAM_SEL_CFIFO1 0x11
+#define ZCP_RAM_SEL_CFIFO2 0x12
+#define ZCP_RAM_SEL_CFIFO3 0x13
+
+typedef union zcp_ram_benable_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t rsvd:15;
+ uint32_t be:17;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t be:17;
+ uint32_t rsvd:15;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_ram_benable_t, *zcp_ram_benable_pt;
+
+typedef union zcp_training_vector_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t train_vec;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t train_vec;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_training_vector_t, *zcp_training_vector_pt;
+
+typedef union zcp_state_machine_u {
+ uint64_t value;
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t state;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t state;
+#endif
+ } ldw;
+#if !defined(_BIG_ENDIAN)
+ uint32_t hdw;
+#endif
+ } bits;
+} zcp_state_machine_t, *zcp_state_machine_pt;
+
+typedef struct zcp_hdr_s {
+ uint16_t zflowid;
+ uint16_t tcp_hdr_len;
+ uint16_t tcp_payld_len;
+ uint16_t head_of_que;
+ uint32_t first_b_offset;
+ boolean_t reach_buf_end;
+ dmaw_type_t dmaw_type;
+ uint8_t win_buf_offset;
+} zcp_hdr_t;
+
+typedef union _zcp_ecc_ctrl {
+ uint64_t value;
+
+ struct {
+#if defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ struct {
+#if defined(_BIT_FIELDS_HTOL)
+ uint32_t dis_dbl : 1;
+ uint32_t res3 : 13;
+ uint32_t cor_dbl : 1;
+ uint32_t cor_sng : 1;
+ uint32_t res2 : 5;
+ uint32_t cor_all : 1;
+ uint32_t res1 : 7;
+ uint32_t cor_lst : 1;
+ uint32_t cor_snd : 1;
+ uint32_t cor_fst : 1;
+#elif defined(_BIT_FIELDS_LTOH)
+ uint32_t cor_fst : 1;
+ uint32_t cor_snd : 1;
+ uint32_t cor_lst : 1;
+ uint32_t res1 : 7;
+ uint32_t cor_all : 1;
+ uint32_t res2 : 5;
+ uint32_t cor_sng : 1;
+ uint32_t cor_dbl : 1;
+ uint32_t res3 : 13;
+ uint32_t dis_dbl : 1;
+#else
+#error one of _BIT_FIELDS_HTOL or _BIT_FIELDS_LTOH must be defined
+#endif
+ } w0;
+
+#if !defined(_BIG_ENDIAN)
+ uint32_t w1;
+#endif
+ } bits;
+} zcp_ecc_ctrl_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_NXGE_NXGE_ZCP_HW_H */
diff --git a/usr/src/uts/sun4v/vm/mach_sfmmu.c b/usr/src/uts/sun4v/vm/mach_sfmmu.c
index f96ced6d4e..3347332094 100644
--- a/usr/src/uts/sun4v/vm/mach_sfmmu.c
+++ b/usr/src/uts/sun4v/vm/mach_sfmmu.c
@@ -299,7 +299,7 @@ kdi_tlb_page_lock(caddr_t va, int do_dtlb)
if (ret != H_EOK) {
cmn_err(CE_PANIC, "cpu%d: cannot set permanent mapping for "
- "va=0x%p, hv error code 0x%lux",
+ "va=0x%p, hv error code 0x%lx",
getprocessorid(), (void *)va, ret);
}
}