1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1985-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * Vuid_store.c - Implement the vuid_store.h event storage interface.
31 */
32
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <sys/kmem.h>
36 #include <sys/systm.h>
37 #include <sys/disp.h>
38 #include <sys/vuid_event.h>
39 #include <sys/vuid_state.h>
40 #include <sys/vuid_store.h>
41
42 static void vuid_destroy_seg();
43 static Vuid_seg * vuid_copy_seg();
44 static Vuid_seg * vuid_find_seg();
45 static Vuid_value * vuid_add_value();
46 static Vuid_value * vuid_find_value();
47
48 #ifdef _KERNEL
49 #define vuid_alloc(bytes) \
50 kmem_alloc((bytes), servicing_interrupt())
51 #define vuid_free(ptr, bytes) kmem_free((ptr), (bytes))
52 #else
53 #define vuid_alloc(bytes) malloc((bytes))
54 #define vuid_free(ptr, bytes) free((ptr))
55 #endif /* _KERNEL */
56
57 void
vuid_set_value(client_state_ptr,event)58 vuid_set_value(client_state_ptr, event)
59 Vuid_state *client_state_ptr;
60 register Firm_event *event;
61 {
62 Vuid_seg **state_ptr = (Vuid_seg **)client_state_ptr;
63 Vuid_seg *state = *state_ptr;
64 register Vuid_seg *seg;
65 register Vuid_value *val_node;
66 register Vuid_value *pair_val_node;
67 register ushort_t offset = vuid_id_offset(event->id);
68 register ushort_t pair = event->pair;
69 int int_bit, val_original;
70
71 /* Get (search for) seg from state assoicated with event */
72 if ((seg = vuid_find_seg(state, vuid_id_addr(event->id))) ==
73 VUID_SEG_NULL) {
74 /* Allocate and initialize new seg for event */
75 seg = (Vuid_seg *) vuid_alloc(sizeof (*seg));
76 bzero((caddr_t)seg, sizeof (*seg));
77 seg->addr = vuid_id_addr(event->id);
78 /* Add the seg to state */
79 *state_ptr = seg;
80 seg->next = state;
81 }
82 int_bit = vuid_get_int_bit(seg, offset);
83 /* See if no value node and event value is not boolean */
84 if ((!int_bit) && vuid_int_value(event->value)) {
85 (void) vuid_add_value(seg, offset);
86 int_bit = 1;
87 }
88 /* If boolean event then set boolean bit */
89 if (!int_bit) {
90 if (event->value)
91 vuid_set_boolean_bit(seg, offset);
92 else
93 vuid_clear_boolean_bit(seg, offset);
94 } else {
95 /* Get (search for) value node (should be there) */
96 val_node = vuid_find_value(seg, offset);
97 val_original = val_node->value;
98 val_node->value = event->value;
99 switch (event->pair_type) {
100
101 case FE_PAIR_DELTA:
102 /* See if value node for pair */
103 if (!vuid_get_int_bit(seg, pair))
104 (void) vuid_add_value(seg, pair);
105 /* Get (search for) value node (should be there) */
106 pair_val_node = vuid_find_value(seg, pair);
107 /* Set pair value to difference */
108 pair_val_node->value = event->value - val_original;
109 break;
110
111 case FE_PAIR_ABSOLUTE:
112 /* See if value node for pair */
113 if (!vuid_get_int_bit(seg, pair))
114 (void) vuid_add_value(seg, pair);
115 /* Get (search for) value node (should be there) */
116 pair_val_node = vuid_find_value(seg, pair);
117 /* Add event value to pair value */
118 pair_val_node->value += event->value;
119 break;
120
121 default:
122 {}
123 }
124 }
125 /* Recursively call vuid_set_value if there is an associated pair */
126 if (event->pair_type == FE_PAIR_SET) {
127 Firm_event pair_event;
128
129 pair_event = *event;
130 pair_event.id = vuid_id_addr(event->id) | pair;
131 pair_event.pair_type = FE_PAIR_NONE;
132 pair_event.pair = 0;
133 vuid_set_value(client_state_ptr, &pair_event);
134 }
135 }
136
137 int
vuid_get_value(client_state,id)138 vuid_get_value(client_state, id)
139 Vuid_state client_state;
140 ushort_t id;
141 {
142 Vuid_seg *state = vuid_cstate_to_state(client_state);
143 register Vuid_seg *seg;
144 Vuid_value *val_node;
145 register ushort_t offset = vuid_id_offset(id);
146
147 /* Get (search for) seg from state assoicated with id */
148 if ((seg = vuid_find_seg(state, vuid_id_addr(id))) == VUID_SEG_NULL)
149 return (0);
150 /* If boolean event (i.e., no ints bit on) then return boolean value */
151 if (!vuid_get_int_bit(seg, offset))
152 return (vuid_get_boolean_bit(seg, offset) != 0);
153 else {
154 /* Get (search for) value node and return value */
155 val_node = vuid_find_value(seg, offset);
156 return (val_node->value);
157 }
158 }
159
160 void
vuid_destroy_state(client_state)161 vuid_destroy_state(client_state)
162 Vuid_state client_state;
163 {
164 Vuid_seg *state = vuid_cstate_to_state(client_state);
165 register Vuid_seg *seg;
166 Vuid_seg *seg_next;
167
168 for (seg = state; seg; seg = seg_next) {
169 seg_next = seg->next;
170 vuid_destroy_seg(seg);
171 }
172 }
173
174 static void
vuid_destroy_seg(seg)175 vuid_destroy_seg(seg)
176 Vuid_seg *seg;
177 {
178 register Vuid_value *val_node;
179 Vuid_value *val_node_next;
180
181 for (val_node = seg->list; val_node; val_node = val_node_next) {
182 val_node_next = val_node->next;
183 vuid_free((caddr_t)val_node, sizeof (Vuid_value));
184 }
185 vuid_free((caddr_t)seg, sizeof (Vuid_seg));
186 }
187
188 Vuid_state
vuid_copy_state(client_state)189 vuid_copy_state(client_state)
190 Vuid_state client_state;
191 {
192 Vuid_seg *state = vuid_cstate_to_state(client_state);
193 register Vuid_seg *seg;
194 Vuid_seg *new_first_seg = VUID_SEG_NULL;
195 register Vuid_seg *new_previous_seg = VUID_SEG_NULL;
196 register Vuid_seg *new_seg;
197
198 for (seg = state; seg; seg = seg->next) {
199 new_seg = vuid_copy_seg(seg);
200 /* Remember first seg as state */
201 if (new_first_seg == VUID_SEG_NULL)
202 new_first_seg = new_seg;
203 /* Link segs together */
204 if (new_previous_seg != VUID_SEG_NULL)
205 new_previous_seg->next = new_seg;
206 /* Remember seg for linking later */
207 new_previous_seg = new_seg;
208 }
209 return ((Vuid_state) new_first_seg);
210 }
211
212 static Vuid_seg *
vuid_copy_seg(seg)213 vuid_copy_seg(seg)
214 Vuid_seg *seg;
215 {
216 register Vuid_value *val_node;
217 Vuid_seg *new_seg;
218 register Vuid_value *new_previous_val = VUID_VALUE_NULL;
219 register Vuid_value *new_val;
220
221 /* Allocate and initialize new seg for event */
222 new_seg = (Vuid_seg *) vuid_alloc(sizeof (*seg));
223 *new_seg = *seg;
224 /* Terminate new pointer with null */
225 new_seg->next = VUID_SEG_NULL;
226 new_seg->list = VUID_VALUE_NULL;
227 /* Copy list elements */
228 for (val_node = seg->list; val_node; val_node = val_node->next) {
229 new_val = (Vuid_value *) vuid_alloc(sizeof (*new_val));
230 *new_val = *val_node;
231 new_val->next = VUID_VALUE_NULL;
232 /* Remember first value as head of list */
233 if (new_seg->list == VUID_VALUE_NULL)
234 new_seg->list = new_val;
235 /* Link vals together */
236 if (new_previous_val != VUID_VALUE_NULL)
237 new_previous_val->next = new_val;
238 /* Remember val for linking later */
239 new_previous_val = new_val;
240 }
241 return (new_seg);
242 }
243
244 static Vuid_seg *
vuid_find_seg(state,addr)245 vuid_find_seg(state, addr)
246 Vuid_seg *state;
247 ushort_t addr;
248 {
249 register Vuid_seg *seg;
250
251 for (seg = state; seg; seg = seg->next) {
252 if (seg->addr == addr)
253 return (seg);
254 }
255 return (VUID_SEG_NULL);
256 }
257
258 static Vuid_value *
vuid_find_value(seg,offset)259 vuid_find_value(seg, offset)
260 Vuid_seg *seg;
261 ushort_t offset;
262 {
263 register Vuid_value *val_node;
264
265 for (val_node = seg->list; val_node; val_node = val_node->next) {
266 if (vuid_id_offset(val_node->offset) == offset)
267 return (val_node);
268 }
269 return (VUID_VALUE_NULL);
270 }
271
272 static Vuid_value *
vuid_add_value(seg,offset)273 vuid_add_value(seg, offset)
274 Vuid_seg *seg;
275 ushort_t offset;
276 {
277 Vuid_value *list_tmp;
278 Vuid_value *val_node;
279
280 /* Allocate and initialize new value node for event */
281 val_node = (Vuid_value *) vuid_alloc(sizeof (*val_node));
282 bzero((caddr_t)val_node, sizeof (*val_node));
283 val_node->offset = offset;
284 /* Add the value node to list */
285 list_tmp = seg->list;
286 seg->list = val_node;
287 val_node->next = list_tmp;
288 vuid_set_int_bit(seg, offset);
289 /* Clear boolean bit for event */
290 vuid_clear_boolean_bit(seg, offset);
291 return (val_node);
292 }
293