1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* 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.
*
* 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 (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _BUSSTAT_H
#define _BUSSTAT_H
#pragma ident "%Z%%M% %I% %E% 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 */
|