/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL 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	_N2PIUPC_TABLES_H
#define	_N2PIUPC_TABLES_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * Table definitions for the N2 PIU performance counter driver.
 *
 * Each table consists of one or more groups of counters.
 *
 * A counter group will a name (used by busstat as the kstat "module" name),
 * have its own set of kstats, and a common event select register.  A group is
 * represented as an n2piu_grp_t.
 *
 * Each counter is represented by an n2piu_cntr_t.  Each has its own register
 * offset (or address), bits for the data it represents, plus an associated
 * register for zeroing it.
 *
 * All registers for n2piu are 64 bit, but a size field can be entered into this
 * structure if registers sizes vary for other implementations (as if this code
 * is leveraged for a future driver).
 *
 * A select register is represented by an n2piu_regsel_t.  This defines the
 * offset or address, and an array of fields which define the events for each
 * counter it services.  All counters need to have an entry in the fields array
 * even if they don't have any representation in a select register.  Please see
 * the explanation of the events array (below) for more information.  Counters
 * without representation in a select register can specify their (non-existant)
 * select register field with mask NONPROG_DUMMY_MASK and offset
 * NONPROG_DUMMY_OFF.
 *
 * This implementation supports only one select register per group.  If more
 * are needed (e.g. if this implementation is used as a template for another
 * device which has multiple select registers per group) the data structures can
 * easily be changed to support an array of them.   Add an array index in the
 * counter structure to associate that counter with a particular select
 * register, and add a field for the number of select registers in the group
 * structure.
 *
 * Each counter has an array of programmable events associated with it, even if
 * it is not programmable.  This array is a series of name/value pairs defined
 * by n2piu_event_t.  The value is the event value loaded into the select
 * register to select that event for that counter.  The last entry in the array
 * is always an entry with a bitmask of LSB-aligned bits of that counter's
 * select register's field's width;  it is usually called the CLEAR_PIC entry.
 * CLEAR_PIC entries are not shown to the user.
 *
 * Note that counters without programmable events still need to define a
 * (small) events array with at least CLEAR_PIC and a single event, so that
 * event's name can display in busstat output.  The CLEAR_PIC entry of
 * nonprogrammable counters can have a value of NONPROG_DUMMY_MASK.
 */

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/kstat.h>
#include "n2piupc_acc.h"

/*
 * Description of a counter's events.  Each counter will have an array of these,
 * to define the events it can be programmed to report.  Nonprogrammable
 * counters still need an array of these, to contain the name busstat will
 * display for it, and a CLEAR_PIC entry.
 */
typedef struct n2piu_event {
	char *name;
	uint64_t value;
} n2piu_event_t;

/*
 * Description of a counter's event selection.  There will be one entry for
 * each counter in the group.
 */
typedef struct n2piu_regsel_fld {
	n2piu_event_t *events_p;
	int num_events;		/* Size of events array. */
	uint64_t event_mask;	/* Width of the event field. */
	int event_offset;	/* Offset of the event field. */
} n2piu_regsel_fld_t;

#define	NUM_EVTS(x)	(sizeof (x) / sizeof (n2piu_event_t))

/*
 * Description of a group's select register.
 */
typedef struct n2piu_regsel {
	off_t regoff;			/* Register offset or address. */
	n2piu_regsel_fld_t *fields_p;	/* select reg subfield descriptions.  */
	int num_fields;			/* Size of the fields array. */
} n2piu_regsel_t;

#define	NUM_FLDS(x)	(sizeof (x) / sizeof (n2piu_regsel_fld_t))

/*
 * Counter description, including its access logistics and how to zero it.
 */
typedef struct n2piu_cntr {
	off_t regoff;		/* Register offset or address. */
	uint64_t fld_mask;	/* Width of the active part of the register */
	off_t zero_regoff;	/* Offset of register used to zero counter. */
	uint64_t zero_value;	/* Value to write to zero_regoff, to clr cntr */
} n2piu_cntr_t;

#define	FULL64BIT	-1ULL	/* Can use this for fld_mask. */

/*
 * Group description.
 */
typedef struct n2piu_grp {
	char *grp_name;		  /* Name, shows up as busstat "module" name. */
	n2piu_regsel_t *regsel_p; /* Select register. */
	n2piu_cntr_t *counters_p; /* Counter definitions. */
	int num_counters;	  /* Size of the counters array. */
	kstat_t **name_kstats_pp; /* Named kstats.  One for all instances. */
} n2piu_grp_t;

#define	NUM_CTRS(x) (sizeof (x) / sizeof (n2piu_cntr_t))

/* N2PIU-specific definitions. */

/* Where groups are in the leaf_grps array. */

#define	NUM_GRPS	4
#define	IMU_GRP		0
#define	MMU_GRP		1
#define	PEU_GRP		2
#define	BIT_ERR_GRP	3

/* The table itself. */
extern n2piu_grp_t *leaf_grps[];

/* Standin symbol for when there is no register. */
#define	NO_REGISTER			(off_t)-1ULL

/*
 * Default event values used in n2piu_event_t structures for non-programmable
 * registers.
 */
#define	NONPROG_DUMMY_MASK	0
#define	NONPROG_DUMMY_OFF	0

/*
 * Event bitmask definitions for all groups.
 */
#define	IMU_CTR_EVT_MASK	0xffull
#define	IMU_CTR_0_EVT_OFF	0
#define	IMU_CTR_1_EVT_OFF	8

#define	MMU_CTR_EVT_MASK	0xffull
#define	MMU_CTR_0_EVT_OFF	0
#define	MMU_CTR_1_EVT_OFF	8

#define	PEU_CTR_01_EVT_MASK	0xffull
#define	PEU_CTR_2_EVT_MASK	0x3ull
#define	PEU_CTR_0_EVT_OFF	0
#define	PEU_CTR_1_EVT_OFF	8
#define	PEU_CTR_2_EVT_OFF	16

#define	BTERR_CTR_0_EVT_MASK	0x1ull
#define	BTERR_CTR_0_EVT_OFF	0

/*
 * Fake the biterr event register to be one with two fields, to store the
 * overall enable/disable event (looks like pic0 reset) and the bterr3 events.
 */

#define	BTERR_CTR_3_EVT_MASK	0xfull
#define	BTERR_CTR_3_EVT_OFF	0

/*
 * Note: this "event" is really an enable, and it serves all 4 PICs.
 *
 * PICs 0,1,2 are from the first counter, PIC3 is from the second counter.
 */
#define	BTERR_CTR_ENABLE_MASK	0x1ull
#define	BTERR_CTR_ENABLE_OFF	63

#define	BTERR_CTR_ENABLE	(BTERR_CTR_ENABLE_MASK << BTERR_CTR_ENABLE_OFF)

/*
 * This register also has a bit to zero the counters.
 */
#define	BTERR_CTR_CLR_MASK	0x1ull
#define	BTERR_CTR_CLR_OFF	62

#define	BTERR_CTR_CLR		(BTERR_CTR_CLR_MASK << BTERR_CTR_CLR_OFF)

#define	BTERR_CTR_ENABLE_AND_CLR	(BTERR_CTR_ENABLE | BTERR_CTR_CLR)

/*
 * Definitions of the different types of events.
 *
 * The first part says which registers these events are for.
 * For example, IMU01 means the IMU performance counters 0 and 1
 */

/* String sought by busstat to locate the event field width "event" entry. */
#define	COMMON_S_CLEAR_PIC			"clear_pic"


#define	IMU01_S_EVT_NONE			"event_none"
#define	IMU01_S_EVT_CLK				"clock_cyc"
#define	IMU01_S_EVT_TOTAL_MONDO			"total_mondo"
#define	IMU01_S_EVT_TOTAL_MSI			"total_msi"
#define	IMU01_S_EVT_NAK_MONDO			"mondo_nak"
#define	IMU01_S_EVT_EQ_WR			"eq_write"
#define	IMU01_S_EVT_EQ_MONDO			"eq_mondo"

#define	IMU01_EVT_NONE				0
#define	IMU01_EVT_CLK				1
#define	IMU01_EVT_TOTAL_MONDO			2
#define	IMU01_EVT_TOTAL_MSI			3
#define	IMU01_EVT_NAK_MONDO			4
#define	IMU01_EVT_EQ_WR				5
#define	IMU01_EVT_EQ_MONDO			6


#define	MMU01_S_EVT_NONE			"event_none"
#define	MMU01_S_EVT_CLK				"clock_cyc"
#define	MMU01_S_EVT_TRANS			"total_transl"
#define	MMU01_S_EVT_STALL			"total_stall_cyc"
#define	MMU01_S_EVT_TRANS_MISS			"total_transl_miss"
#define	MMU01_S_EVT_TBLWLK_STALL		"tblwlk_stall_cyc"
#define	MMU01_S_EVT_BYPASS_TRANSL		"bypass_transl"
#define	MMU01_S_EVT_TRANSL_TRANSL		"transl_transl"
#define	MMU01_S_EVT_FLOW_CNTL_STALL		"flow_stall_cyc"
#define	MMU01_S_EVT_FLUSH_CACHE_ENT		"cache_entr_flush"

#define	MMU01_EVT_NONE				0
#define	MMU01_EVT_CLK				1
#define	MMU01_EVT_TRANS				2
#define	MMU01_EVT_STALL				3
#define	MMU01_EVT_TRANS_MISS			4
#define	MMU01_EVT_TBLWLK_STALL			5
#define	MMU01_EVT_BYPASS_TRANSL			6
#define	MMU01_EVT_TRANSL_TRANSL			7
#define	MMU01_EVT_FLOW_CNTL_STALL		8
#define	MMU01_EVT_FLUSH_CACHE_ENT		9


#define	PEU2_S_EVT_NONE				"event_none"
#define	PEU2_S_EVT_NONPST_CMPL_TIME		"npost_compl_time"
#define	PEU2_S_EVT_XMIT_DATA			"xmit_data"
#define	PEU2_S_EVT_RCVD_DATA			"rcvd_data"

#define	PEU2_EVT_NONE				0
#define	PEU2_EVT_NONPST_CMPL_TIME		1
#define	PEU2_EVT_XMIT_DATA			2
#define	PEU2_EVT_RCVD_DATA			3


#define	PEU01_S_EVT_NONE			"event_none"
#define	PEU01_S_EVT_CLK				"clock_cyc"
#define	PEU01_S_EVT_COMPL			"compl_recvd"
#define	PEU01_S_EVT_XMT_POST_CR_UNAV		"post_cr_unav_cyc"
#define	PEU01_S_EVT_XMT_NPOST_CR_UNAV		"npost_cr_unav_cyc"
#define	PEU01_S_EVT_XMT_CMPL_CR_UNAV		"compl_cr_unav_cyc"
#define	PEU01_S_EVT_XMT_ANY_CR_UNAV		"trans_cr_any_unav"
#define	PEU01_S_EVT_RETRY_CR_UNAV		"retry_cr_unav"
#define	PEU01_S_EVT_MEMRD_PKT_RCVD		"recvd_mem_rd_pkt"
#define	PEU01_S_EVT_MEMWR_PKT_RCVD		"recvd_mem_wr_pkt"
#define	PEU01_S_EVT_RCV_CR_THRESH		"recv_cr_thresh"
#define	PEU01_S_EVT_RCV_PST_HDR_CR_EXH		"recv_hdr_cr_exh_cyc"
#define	PEU01_S_EVT_RCV_PST_DA_CR_MPS		"recv_post_da_cr_mps"
#define	PEU01_S_EVT_RCV_NPST_HDR_CR_EXH		"recv_npost_hdr_cr_exh"
#define	PEU01_S_EVT_RCVR_L0S			"recvr_l0s_cyc"
#define	PEU01_S_EVT_RCVR_L0S_TRANS		"recvr_l0s_trans"
#define	PEU01_S_EVT_XMTR_L0S			"trans_l0s_cyc"
#define	PEU01_S_EVT_XMTR_L0S_TRANS		"trans_l0s_trans"
#define	PEU01_S_EVT_RCVR_ERR			"recvr_err"
#define	PEU01_S_EVT_BAD_TLP			"bad_tlp"
#define	PEU01_S_EVT_BAD_DLLP			"bad_dllp"
#define	PEU01_S_EVT_REPLAY_ROLLOVER		"replay_rollover"
#define	PEU01_S_EVT_REPLAY_TMO			"replay_to"

#define	PEU01_EVT_NONE				0x0
#define	PEU01_EVT_CLK				0x1
#define	PEU01_EVT_COMPL				0x2
#define	PEU01_EVT_XMT_POST_CR_UNAV		0x10
#define	PEU01_EVT_XMT_NPOST_CR_UNAV		0x11
#define	PEU01_EVT_XMT_CMPL_CR_UNAV		0x12
#define	PEU01_EVT_XMT_ANY_CR_UNAV		0x13
#define	PEU01_EVT_RETRY_CR_UNAV			0x14
#define	PEU01_EVT_MEMRD_PKT_RCVD		0x20
#define	PEU01_EVT_MEMWR_PKT_RCVD		0x21
#define	PEU01_EVT_RCV_CR_THRESH			0x22
#define	PEU01_EVT_RCV_PST_HDR_CR_EXH		0x23
#define	PEU01_EVT_RCV_PST_DA_CR_MPS		0x24
#define	PEU01_EVT_RCV_NPST_HDR_CR_EXH		0x25
#define	PEU01_EVT_RCVR_L0S			0x30
#define	PEU01_EVT_RCVR_L0S_TRANS		0x31
#define	PEU01_EVT_XMTR_L0S			0x32
#define	PEU01_EVT_XMTR_L0S_TRANS		0x33
#define	PEU01_EVT_RCVR_ERR			0x40
#define	PEU01_EVT_BAD_TLP			0x42
#define	PEU01_EVT_BAD_DLLP			0x43
#define	PEU01_EVT_REPLAY_ROLLOVER		0x44
#define	PEU01_EVT_REPLAY_TMO			0x47

/*
 * BTERR counter 3 is presented by the device as one register with 8 different
 * counters.  Since busstat displays in decimal and not in hex, display of the
 * raw data is impractical except to make a non-zero test.  Fake that this
 * register has multiple modes, so that each lane can be shown separately.
 * Then one can use Busstat capabilities to display alternating events of a
 * register.
 */

#define	BTERR3_S_EVT_NONE			"event_none"
#define	BTERR3_S_EVT_ENC_ALL			"encd_err_ln_all"
#define	BTERR3_S_EVT_ENC_LANE_0			"encd_err_ln_0"
#define	BTERR3_S_EVT_ENC_LANE_1			"encd_err_ln_1"
#define	BTERR3_S_EVT_ENC_LANE_2			"encd_err_ln_2"
#define	BTERR3_S_EVT_ENC_LANE_3			"encd_err_ln_3"
#define	BTERR3_S_EVT_ENC_LANE_4			"encd_err_ln_4"
#define	BTERR3_S_EVT_ENC_LANE_5			"encd_err_ln_5"
#define	BTERR3_S_EVT_ENC_LANE_6			"encd_err_ln_6"
#define	BTERR3_S_EVT_ENC_LANE_7			"encd_err_ln_7"

#define	BTERR3_EVT_ENC_NONE			0
#define	BTERR3_EVT_ENC_ALL			1
#define	BTERR3_EVT_ENC_LANE_0			2
#define	BTERR3_EVT_ENC_LANE_1			3
#define	BTERR3_EVT_ENC_LANE_2			4
#define	BTERR3_EVT_ENC_LANE_3			5
#define	BTERR3_EVT_ENC_LANE_4			6
#define	BTERR3_EVT_ENC_LANE_5			7
#define	BTERR3_EVT_ENC_LANE_6			8
#define	BTERR3_EVT_ENC_LANE_7			9

/*
 * For non-programmable registers, include an n2piu_event_t which has two
 * fields, a default field (which gives the field a name even though it
 * can't be programmed, and clear_pic which busstat needs.
 */
#define	BTERR2_S_EVT_PRE			"phys_rcvr_errs"

#define	BTERR2_EVT_PRE				0

#define	BTERR1_S_EVT_BTLP			"bad_tlps"

#define	BTERR1_EVT_BTLP				0

/*
 * Note: All 4 biterr counter fields (split among two counter registers) are
 * tied together with a single enable.  Treat the first field as programmable
 * to provide a way to reset the counter set.
 */
#define	BTERR0_S_EVT_RESET	"reset_bterr"	/* All biterr counter zero */
#define	BTERR0_S_EVT_BDLLP	"bad_dllps"

#define	BTERR0_EVT_RESET	0
#define	BTERR0_EVT_BDLLP	1

/*
 * First bit error counter register has three counters.  Here are the
 * placements of these counters within the (virtual) registers.
 */
#define	BE1_BAD_DLLP_MASK	0xff000000ULL
#define	BE1_BAD_TLP_MASK	0xff0000ULL
#define	BE1_BAD_PRE_MASK	0x3ffULL
#define	BE2_8_10_MASK		FULL64BIT

#ifdef	__cplusplus
}
#endif

#endif	/* _N2PIUPC_TABLES_H */