diff options
author | girish <none@none> | 2006-11-22 11:47:19 -0800 |
---|---|---|
committer | girish <none@none> | 2006-11-22 11:47:19 -0800 |
commit | 4496171313bed39e96f21bc2f9faf2868e267ae3 (patch) | |
tree | d396d1596da772a70a5e7c1986a2ef9600c1fbf7 /usr/src | |
parent | 4e0386dffa68d848cdca5a6308d652c20d6fc454 (diff) | |
download | illumos-gate-4496171313bed39e96f21bc2f9faf2868e267ae3.tar.gz |
FWARC/2006/175 MD definition for N2 CWQ
FWARC/2006/201 sun4v error handling update
FWARC/2006/425 NCS HV API Update 2
FWARC/2006/429 Niagara2 Perf Regs HV API
FWARC/2006/474 pci io hv iommu attributes update
FWARC/2006/481 Niagara-2 Random Number Generator API
FWARC/2006/524 Niagara2 Network Interface Unit Hypervisor API
FWARC/2006/556 NIU/SIU Device Tree Bindings and Machine Description Definitions
FWARC/2006/567 Niagara Crypto & RNG compatible property update
PSARC/2006/459 Huron 1u/2u Platform Support
PSARC/2006/520 Niagara 2 Random Number Generator
PSARC/2006/521 Niagara 2 Cryptographic Provider
PSARC/2006/645 Niagara II NIU 10Gbit Ethernet Driver
6477049 ON support for UltraSPARC-T2 processor
6375797 Add support for SUN4V IOMMU extensions
6480942 Crypto support for UltraSPARC-T2 processor
6480959 NIU support for UltraSPARC-T2 processor
6483040 ON platform support for Huron (SPARC-Enterprise-T5120 & SPARC-Enterprise-T5220)
Diffstat (limited to 'usr/src')
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 **)®spec, (uint_t *)®len) != 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 **)®spec, (uint_t *)®len) != 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 **)®_p, ®len) + != 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)®_p, ®len) != 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)®_p, ®len) + != 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, ðerbroadcastaddr) == 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, ®size); + 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, ®size); + 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, ®size); + 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, ®size); + 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, ®size); + 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, ®size); + 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, ®size); + 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 *)®, sizeof (uint64_t)); + regdata = 0; + retry = 1; + + for (i = 0; i < retry; i++) { + NXGE_REG_RD64(nxgep->npi_handle, reg, ®data); + } + bcopy((char *)®data, (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, + ¶m_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)¶m_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)®_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); } } |