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 /*
28 * Vuid_store.c - Implement the vuid_store.h event storage interface.
29 */
30
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/kmem.h>
34 #include <sys/systm.h>
35 #include <sys/disp.h>
36 #include <sys/vuid_event.h>
37 #include <sys/vuid_state.h>
38 #include <sys/vuid_store.h>
39
40 static void vuid_destroy_seg();
41 static Vuid_seg * vuid_copy_seg();
42 static Vuid_seg * vuid_find_seg();
43 static Vuid_value * vuid_add_value();
44 static Vuid_value * vuid_find_value();
45
46 #ifdef _KERNEL
47 #define vuid_alloc(bytes) \
48 kmem_alloc((bytes), servicing_interrupt())
49 #define vuid_free(ptr, bytes) kmem_free((ptr), (bytes))
50 #else
51 #define vuid_alloc(bytes) malloc((bytes))
52 #define vuid_free(ptr, bytes) free((ptr))
53 #endif /* _KERNEL */
54
55 void
vuid_set_value(client_state_ptr,event)56 vuid_set_value(client_state_ptr, event)
57 Vuid_state *client_state_ptr;
58 register Firm_event *event;
59 {
60 Vuid_seg **state_ptr = (Vuid_seg **)client_state_ptr;
61 Vuid_seg *state = *state_ptr;
62 register Vuid_seg *seg;
63 register Vuid_value *val_node;
64 register Vuid_value *pair_val_node;
65 register ushort_t offset = vuid_id_offset(event->id);
66 register ushort_t pair = event->pair;
67 int int_bit, val_original;
68
69 /* Get (search for) seg from state assoicated with event */
70 if ((seg = vuid_find_seg(state, vuid_id_addr(event->id))) ==
71 VUID_SEG_NULL) {
72 /* Allocate and initialize new seg for event */
73 seg = (Vuid_seg *) vuid_alloc(sizeof (*seg));
74 bzero((caddr_t)seg, sizeof (*seg));
75 seg->addr = vuid_id_addr(event->id);
76 /* Add the seg to state */
77 *state_ptr = seg;
78 seg->next = state;
79 }
80 int_bit = vuid_get_int_bit(seg, offset);
81 /* See if no value node and event value is not boolean */
82 if ((!int_bit) && vuid_int_value(event->value)) {
83 (void) vuid_add_value(seg, offset);
84 int_bit = 1;
85 }
86 /* If boolean event then set boolean bit */
87 if (!int_bit) {
88 if (event->value)
89 vuid_set_boolean_bit(seg, offset);
90 else
91 vuid_clear_boolean_bit(seg, offset);
92 } else {
93 /* Get (search for) value node (should be there) */
94 val_node = vuid_find_value(seg, offset);
95 val_original = val_node->value;
96 val_node->value = event->value;
97 switch (event->pair_type) {
98
99 case FE_PAIR_DELTA:
100 /* See if value node for pair */
101 if (!vuid_get_int_bit(seg, pair))
102 (void) vuid_add_value(seg, pair);
103 /* Get (search for) value node (should be there) */
104 pair_val_node = vuid_find_value(seg, pair);
105 /* Set pair value to difference */
106 pair_val_node->value = event->value - val_original;
107 break;
108
109 case FE_PAIR_ABSOLUTE:
110 /* See if value node for pair */
111 if (!vuid_get_int_bit(seg, pair))
112 (void) vuid_add_value(seg, pair);
113 /* Get (search for) value node (should be there) */
114 pair_val_node = vuid_find_value(seg, pair);
115 /* Add event value to pair value */
116 pair_val_node->value += event->value;
117 break;
118
119 default:
120 {}
121 }
122 }
123 /* Recursively call vuid_set_value if there is an associated pair */
124 if (event->pair_type == FE_PAIR_SET) {
125 Firm_event pair_event;
126
127 pair_event = *event;
128 pair_event.id = vuid_id_addr(event->id) | pair;
129 pair_event.pair_type = FE_PAIR_NONE;
130 pair_event.pair = 0;
131 vuid_set_value(client_state_ptr, &pair_event);
132 }
133 }
134
135 int
vuid_get_value(client_state,id)136 vuid_get_value(client_state, id)
137 Vuid_state client_state;
138 ushort_t id;
139 {
140 Vuid_seg *state = vuid_cstate_to_state(client_state);
141 register Vuid_seg *seg;
142 Vuid_value *val_node;
143 register ushort_t offset = vuid_id_offset(id);
144
145 /* Get (search for) seg from state assoicated with id */
146 if ((seg = vuid_find_seg(state, vuid_id_addr(id))) == VUID_SEG_NULL)
147 return (0);
148 /* If boolean event (i.e., no ints bit on) then return boolean value */
149 if (!vuid_get_int_bit(seg, offset))
150 return (vuid_get_boolean_bit(seg, offset) != 0);
151 else {
152 /* Get (search for) value node and return value */
153 val_node = vuid_find_value(seg, offset);
154 return (val_node->value);
155 }
156 }
157
158 void
vuid_destroy_state(client_state)159 vuid_destroy_state(client_state)
160 Vuid_state client_state;
161 {
162 Vuid_seg *state = vuid_cstate_to_state(client_state);
163 register Vuid_seg *seg;
164 Vuid_seg *seg_next;
165
166 for (seg = state; seg; seg = seg_next) {
167 seg_next = seg->next;
168 vuid_destroy_seg(seg);
169 }
170 }
171
172 static void
vuid_destroy_seg(seg)173 vuid_destroy_seg(seg)
174 Vuid_seg *seg;
175 {
176 register Vuid_value *val_node;
177 Vuid_value *val_node_next;
178
179 for (val_node = seg->list; val_node; val_node = val_node_next) {
180 val_node_next = val_node->next;
181 vuid_free((caddr_t)val_node, sizeof (Vuid_value));
182 }
183 vuid_free((caddr_t)seg, sizeof (Vuid_seg));
184 }
185
186 Vuid_state
vuid_copy_state(client_state)187 vuid_copy_state(client_state)
188 Vuid_state client_state;
189 {
190 Vuid_seg *state = vuid_cstate_to_state(client_state);
191 register Vuid_seg *seg;
192 Vuid_seg *new_first_seg = VUID_SEG_NULL;
193 register Vuid_seg *new_previous_seg = VUID_SEG_NULL;
194 register Vuid_seg *new_seg;
195
196 for (seg = state; seg; seg = seg->next) {
197 new_seg = vuid_copy_seg(seg);
198 /* Remember first seg as state */
199 if (new_first_seg == VUID_SEG_NULL)
200 new_first_seg = new_seg;
201 /* Link segs together */
202 if (new_previous_seg != VUID_SEG_NULL)
203 new_previous_seg->next = new_seg;
204 /* Remember seg for linking later */
205 new_previous_seg = new_seg;
206 }
207 return ((Vuid_state) new_first_seg);
208 }
209
210 static Vuid_seg *
vuid_copy_seg(seg)211 vuid_copy_seg(seg)
212 Vuid_seg *seg;
213 {
214 register Vuid_value *val_node;
215 Vuid_seg *new_seg;
216 register Vuid_value *new_previous_val = VUID_VALUE_NULL;
217 register Vuid_value *new_val;
218
219 /* Allocate and initialize new seg for event */
220 new_seg = (Vuid_seg *) vuid_alloc(sizeof (*seg));
221 *new_seg = *seg;
222 /* Terminate new pointer with null */
223 new_seg->next = VUID_SEG_NULL;
224 new_seg->list = VUID_VALUE_NULL;
225 /* Copy list elements */
226 for (val_node = seg->list; val_node; val_node = val_node->next) {
227 new_val = (Vuid_value *) vuid_alloc(sizeof (*new_val));
228 *new_val = *val_node;
229 new_val->next = VUID_VALUE_NULL;
230 /* Remember first value as head of list */
231 if (new_seg->list == VUID_VALUE_NULL)
232 new_seg->list = new_val;
233 /* Link vals together */
234 if (new_previous_val != VUID_VALUE_NULL)
235 new_previous_val->next = new_val;
236 /* Remember val for linking later */
237 new_previous_val = new_val;
238 }
239 return (new_seg);
240 }
241
242 static Vuid_seg *
vuid_find_seg(state,addr)243 vuid_find_seg(state, addr)
244 Vuid_seg *state;
245 ushort_t addr;
246 {
247 register Vuid_seg *seg;
248
249 for (seg = state; seg; seg = seg->next) {
250 if (seg->addr == addr)
251 return (seg);
252 }
253 return (VUID_SEG_NULL);
254 }
255
256 static Vuid_value *
vuid_find_value(seg,offset)257 vuid_find_value(seg, offset)
258 Vuid_seg *seg;
259 ushort_t offset;
260 {
261 register Vuid_value *val_node;
262
263 for (val_node = seg->list; val_node; val_node = val_node->next) {
264 if (vuid_id_offset(val_node->offset) == offset)
265 return (val_node);
266 }
267 return (VUID_VALUE_NULL);
268 }
269
270 static Vuid_value *
vuid_add_value(seg,offset)271 vuid_add_value(seg, offset)
272 Vuid_seg *seg;
273 ushort_t offset;
274 {
275 Vuid_value *list_tmp;
276 Vuid_value *val_node;
277
278 /* Allocate and initialize new value node for event */
279 val_node = (Vuid_value *) vuid_alloc(sizeof (*val_node));
280 bzero((caddr_t)val_node, sizeof (*val_node));
281 val_node->offset = offset;
282 /* Add the value node to list */
283 list_tmp = seg->list;
284 seg->list = val_node;
285 val_node->next = list_tmp;
286 vuid_set_int_bit(seg, offset);
287 /* Clear boolean bit for event */
288 vuid_clear_boolean_bit(seg, offset);
289 return (val_node);
290 }
291