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 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 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 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 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 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 * 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 * 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 * 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 * 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