1/* 2 * gh.c 3 * 4 * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 * 6 * Copyright (C) 2005-2006 Texas Instruments, Inc. 7 * 8 * This package is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 */ 16 17#include <linux/types.h> 18 19#include <dspbridge/host_os.h> 20 21#include <dspbridge/gs.h> 22 23#include <dspbridge/gh.h> 24 25struct element { 26 struct element *next; 27 u8 data[1]; 28}; 29 30struct gh_t_hash_tab { 31 u16 max_bucket; 32 u16 val_size; 33 struct element **buckets; 34 u16(*hash) (void *, u16); 35 bool(*match) (void *, void *); 36 void (*delete) (void *); 37}; 38 39static void noop(void *p); 40static s32 cur_init; 41static void myfree(void *ptr, s32 size); 42 43/* 44 * ======== gh_create ======== 45 */ 46 47struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, 48 u16(*hash) (void *, u16), bool(*match) (void *, 49 void *), 50 void (*delete) (void *)) 51{ 52 struct gh_t_hash_tab *hash_tab; 53 u16 i; 54 hash_tab = 55 (struct gh_t_hash_tab *)gs_alloc(sizeof(struct gh_t_hash_tab)); 56 if (hash_tab == NULL) 57 return NULL; 58 hash_tab->max_bucket = max_bucket; 59 hash_tab->val_size = val_size; 60 hash_tab->hash = hash; 61 hash_tab->match = match; 62 hash_tab->delete = delete == NULL ? noop : delete; 63 64 hash_tab->buckets = (struct element **) 65 gs_alloc(sizeof(struct element *) * max_bucket); 66 if (hash_tab->buckets == NULL) { 67 gh_delete(hash_tab); 68 return NULL; 69 } 70 71 for (i = 0; i < max_bucket; i++) 72 hash_tab->buckets[i] = NULL; 73 74 return hash_tab; 75} 76 77/* 78 * ======== gh_delete ======== 79 */ 80void gh_delete(struct gh_t_hash_tab *hash_tab) 81{ 82 struct element *elem, *next; 83 u16 i; 84 85 if (hash_tab != NULL) { 86 if (hash_tab->buckets != NULL) { 87 for (i = 0; i < hash_tab->max_bucket; i++) { 88 for (elem = hash_tab->buckets[i]; elem != NULL; 89 elem = next) { 90 next = elem->next; 91 (*hash_tab->delete) (elem->data); 92 myfree(elem, 93 sizeof(struct element) - 1 + 94 hash_tab->val_size); 95 } 96 } 97 98 myfree(hash_tab->buckets, sizeof(struct element *) 99 * hash_tab->max_bucket); 100 } 101 102 myfree(hash_tab, sizeof(struct gh_t_hash_tab)); 103 } 104} 105 106/* 107 * ======== gh_exit ======== 108 */ 109 110void gh_exit(void) 111{ 112 if (cur_init-- == 1) 113 gs_exit(); 114 115} 116 117/* 118 * ======== gh_find ======== 119 */ 120 121void *gh_find(struct gh_t_hash_tab *hash_tab, void *key) 122{ 123 struct element *elem; 124 125 elem = hash_tab->buckets[(*hash_tab->hash) (key, hash_tab->max_bucket)]; 126 127 for (; elem; elem = elem->next) { 128 if ((*hash_tab->match) (key, elem->data)) 129 return elem->data; 130 } 131 132 return NULL; 133} 134 135/* 136 * ======== gh_init ======== 137 */ 138 139void gh_init(void) 140{ 141 if (cur_init++ == 0) 142 gs_init(); 143} 144 145/* 146 * ======== gh_insert ======== 147 */ 148 149void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value) 150{ 151 struct element *elem; 152 u16 i; 153 char *src, *dst; 154 155 elem = (struct element *)gs_alloc(sizeof(struct element) - 1 + 156 hash_tab->val_size); 157 if (elem != NULL) { 158 159 dst = (char *)elem->data; 160 src = (char *)value; 161 for (i = 0; i < hash_tab->val_size; i++) 162 *dst++ = *src++; 163 164 i = (*hash_tab->hash) (key, hash_tab->max_bucket); 165 elem->next = hash_tab->buckets[i]; 166 hash_tab->buckets[i] = elem; 167 168 return elem->data; 169 } 170 171 return NULL; 172} 173 174/* 175 * ======== noop ======== 176 */ 177/* ARGSUSED */ 178static void noop(void *p) 179{ 180 p = p; /* stifle compiler warning */ 181} 182 183/* 184 * ======== myfree ======== 185 */ 186static void myfree(void *ptr, s32 size) 187{ 188 gs_free(ptr); 189} 190 191#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 192/** 193 * gh_iterate() - This function goes through all the elements in the hash table 194 * looking for the dsp symbols. 195 * @hash_tab: Hash table 196 * @callback: pointer to callback function 197 * @user_data: User data, contains the find_symbol_context pointer 198 * 199 */ 200void gh_iterate(struct gh_t_hash_tab *hash_tab, 201 void (*callback)(void *, void *), void *user_data) 202{ 203 struct element *elem; 204 u32 i; 205 206 if (hash_tab && hash_tab->buckets) 207 for (i = 0; i < hash_tab->max_bucket; i++) { 208 elem = hash_tab->buckets[i]; 209 while (elem) { 210 callback(&elem->data, user_data); 211 elem = elem->next; 212 } 213 } 214} 215#endif 216