/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef	_BUSSTAT_H
#define	_BUSSTAT_H


#pragma ident	"@(#)busstat.h	1.2	99/09/21 SMI"

/*
 * busstat works by reading and writing from/to kstat's which are
 * exported by drivers on the system.
 *
 * busstat parses the command line it is given and builds up a
 * pair of linked list's to represent the various options specified.
 * An example command line is given below..
 *
 * -w ac2,pic0=wio_pkts,pic1=rbio_pkts -w ac2,pic0=rto_pkts,pic1=rto_pkts -r ac5
 * =============================================================================
 *
 * ______
 * |    |
 * | ac2|->wio_pkts->rto_pkts
 * |pic0|    |            |
 * |    |    -------<------
 * ------
 *    |
 *    |
 * ______
 * |    |
 * | ac2|->rbio_pkts->rto_pkts
 * |pic1|     |            |
 * |    |     --------<-----
 * ------
 *    |
 *    |
 * ______
 * |    |
 * | ac5|->evt
 * |pic0|
 * |    |
 * ------
 *   |
 *   |
 * ______
 * |    |
 * | ac5|->evt
 * |pic1|
 * |    |
 * ------
 *
 * The above diagram shows the lists created after the initial parsing.
 *
 * Each device instance/pic is represented by a device node. Hanging off
 * that is at least one event node.
 *
 * Event nodes come in two different types. Nodes that are the result of a -r
 * operation will have the r_w field in their parent dev_node set to EVT_READ,
 * and most of their other fields set to zero or NULL. An event node that was
 * created because of a -w operation (r_w = EVT_WRITE) will have all it's fields
 * filled in. When a device node is created, an  event node is automatically
 * created and marked as EVT_READ. If the device node was created as the result
 * of a -r operation, nothing more happens. But if it was a -w operation, then
 * the event node is modified (r_w changed to EVT_WRITE, event pcr mask and
 * event name written if known).
 *
 * Setting events : work along the list of dev_nodes, for each device node check
 * the event node pointed to by evt_node, if it is marked as EVT_WRITE in the
 * corresponding r_w array, if so set the event stored in the node.
 *
 * Reading events : work along the list of dev_nodes, for each device node check
 * the event node pointed to by evt_node, if it is marked EVT_WRITE, just read
 * the event count from the appropiate PIC and store it in the node. If the node
 * is EVT_READ however, read the PCR, determine the event name, store it in the
 * node along with the event count.
 *
 * Multiplexing is handled by cycling through the event nodes. The event nodes
 * are on a circular list, which allows each pic to be multiplexing between
 * different numbers of events.
 */

#define	TRUE	1
#define	FALSE	0
#define	FAIL	-1

#define	READ_EVT	1
#define	WRITE_EVT	0

#define	EVT_READ	0x1
#define	EVT_WRITE	0x2
#define	ONE_INST_CALL	0x4
#define	ALL_INST_CALL	0x8

#define	STATE_INIT	0x10	/* Initial state of node when created */
#define	STATE_INST	0x20	/* Node was created by specific instance call */
#define	STATE_ALL	0x40	/* Node was created by call for all instances */

#define	NANO		1000000000	/* To convert from nanosecs to secs */

#define	PIC_STR_LEN	3

#define	EVT_STR		-1

typedef struct evt_node {
	char		evt_name[KSTAT_STRLEN];	/* The event name */
	uint64_t	prev_count;	/* The previous count for this evt */
	uint64_t	total;		/* Total count for this event */
	uint64_t	evt_pcr_mask;	/* PCR mask for this event */
	struct evt_node *next;
} evt_node_t;

typedef struct dev_node {
	char		name[KSTAT_STRLEN];	/* Device name e.g. ac */
	int		dev_inst;	/* Device instance number */
	int		pic_num;	/* PIC number. */
	kstat_t		*cnt_ksp;	/* "counters" kstat pointer */
	kstat_t		*pic_ksp;	/* pointer to picN kstat */
	int		r_w;		/* r_w flag */
	int		state;		/* state flag */
	struct evt_node	*evt_node;	/* ptr to current evt_node */
	struct dev_node	*next;
} dev_node_t;

#endif	/* _BUSSTAT_H */
