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