xref: /aosp_15_r20/external/pciutils/lib/names-hash.c (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker  *	The PCI Library -- ID to Name Hash
3*c2e0c6b5SAndroid Build Coastguard Worker  *
4*c2e0c6b5SAndroid Build Coastguard Worker  *	Copyright (c) 1997--2008 Martin Mares <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker  *
6*c2e0c6b5SAndroid Build Coastguard Worker  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker  *
8*c2e0c6b5SAndroid Build Coastguard Worker  *	SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker  */
10*c2e0c6b5SAndroid Build Coastguard Worker 
11*c2e0c6b5SAndroid Build Coastguard Worker #include <string.h>
12*c2e0c6b5SAndroid Build Coastguard Worker 
13*c2e0c6b5SAndroid Build Coastguard Worker #include "internal.h"
14*c2e0c6b5SAndroid Build Coastguard Worker #include "names.h"
15*c2e0c6b5SAndroid Build Coastguard Worker 
16*c2e0c6b5SAndroid Build Coastguard Worker struct id_bucket {
17*c2e0c6b5SAndroid Build Coastguard Worker   struct id_bucket *next;
18*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int full;
19*c2e0c6b5SAndroid Build Coastguard Worker };
20*c2e0c6b5SAndroid Build Coastguard Worker 
21*c2e0c6b5SAndroid Build Coastguard Worker #ifdef __GNUC__
22*c2e0c6b5SAndroid Build Coastguard Worker #define BUCKET_ALIGNMENT __alignof__(struct id_bucket)
23*c2e0c6b5SAndroid Build Coastguard Worker #else
24*c2e0c6b5SAndroid Build Coastguard Worker union id_align {
25*c2e0c6b5SAndroid Build Coastguard Worker   struct id_bucket *next;
26*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int full;
27*c2e0c6b5SAndroid Build Coastguard Worker };
28*c2e0c6b5SAndroid Build Coastguard Worker #define BUCKET_ALIGNMENT sizeof(union id_align)
29*c2e0c6b5SAndroid Build Coastguard Worker #endif
30*c2e0c6b5SAndroid Build Coastguard Worker #define BUCKET_ALIGN(n) ((n)+BUCKET_ALIGNMENT-(n)%BUCKET_ALIGNMENT)
31*c2e0c6b5SAndroid Build Coastguard Worker 
id_alloc(struct pci_access * a,unsigned int size)32*c2e0c6b5SAndroid Build Coastguard Worker static void *id_alloc(struct pci_access *a, unsigned int size)
33*c2e0c6b5SAndroid Build Coastguard Worker {
34*c2e0c6b5SAndroid Build Coastguard Worker   struct id_bucket *buck = a->current_id_bucket;
35*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int pos;
36*c2e0c6b5SAndroid Build Coastguard Worker 
37*c2e0c6b5SAndroid Build Coastguard Worker   if (!a->id_hash)
38*c2e0c6b5SAndroid Build Coastguard Worker     {
39*c2e0c6b5SAndroid Build Coastguard Worker       a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE);
40*c2e0c6b5SAndroid Build Coastguard Worker       memset(a->id_hash, 0, sizeof(struct id_entry *) * HASH_SIZE);
41*c2e0c6b5SAndroid Build Coastguard Worker     }
42*c2e0c6b5SAndroid Build Coastguard Worker 
43*c2e0c6b5SAndroid Build Coastguard Worker   if (!buck || buck->full + size > BUCKET_SIZE)
44*c2e0c6b5SAndroid Build Coastguard Worker     {
45*c2e0c6b5SAndroid Build Coastguard Worker       buck = pci_malloc(a, BUCKET_SIZE);
46*c2e0c6b5SAndroid Build Coastguard Worker       buck->next = a->current_id_bucket;
47*c2e0c6b5SAndroid Build Coastguard Worker       a->current_id_bucket = buck;
48*c2e0c6b5SAndroid Build Coastguard Worker       buck->full = BUCKET_ALIGN(sizeof(struct id_bucket));
49*c2e0c6b5SAndroid Build Coastguard Worker     }
50*c2e0c6b5SAndroid Build Coastguard Worker   pos = buck->full;
51*c2e0c6b5SAndroid Build Coastguard Worker   buck->full = BUCKET_ALIGN(buck->full + size);
52*c2e0c6b5SAndroid Build Coastguard Worker   return (byte *)buck + pos;
53*c2e0c6b5SAndroid Build Coastguard Worker }
54*c2e0c6b5SAndroid Build Coastguard Worker 
id_hash(int cat,u32 id12,u32 id34)55*c2e0c6b5SAndroid Build Coastguard Worker static inline unsigned int id_hash(int cat, u32 id12, u32 id34)
56*c2e0c6b5SAndroid Build Coastguard Worker {
57*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int h;
58*c2e0c6b5SAndroid Build Coastguard Worker 
59*c2e0c6b5SAndroid Build Coastguard Worker   h = id12 ^ (id34 << 3) ^ (cat << 5);
60*c2e0c6b5SAndroid Build Coastguard Worker   return h % HASH_SIZE;
61*c2e0c6b5SAndroid Build Coastguard Worker }
62*c2e0c6b5SAndroid Build Coastguard Worker 
63*c2e0c6b5SAndroid Build Coastguard Worker int
pci_id_insert(struct pci_access * a,int cat,int id1,int id2,int id3,int id4,char * text,enum id_entry_src src)64*c2e0c6b5SAndroid Build Coastguard Worker pci_id_insert(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, char *text, enum id_entry_src src)
65*c2e0c6b5SAndroid Build Coastguard Worker {
66*c2e0c6b5SAndroid Build Coastguard Worker   u32 id12 = id_pair(id1, id2);
67*c2e0c6b5SAndroid Build Coastguard Worker   u32 id34 = id_pair(id3, id4);
68*c2e0c6b5SAndroid Build Coastguard Worker   unsigned int h = id_hash(cat, id12, id34);
69*c2e0c6b5SAndroid Build Coastguard Worker   struct id_entry *n = a->id_hash ? a->id_hash[h] : NULL;
70*c2e0c6b5SAndroid Build Coastguard Worker   int len = strlen(text);
71*c2e0c6b5SAndroid Build Coastguard Worker 
72*c2e0c6b5SAndroid Build Coastguard Worker   while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat))
73*c2e0c6b5SAndroid Build Coastguard Worker     n = n->next;
74*c2e0c6b5SAndroid Build Coastguard Worker   if (n)
75*c2e0c6b5SAndroid Build Coastguard Worker     return 1;
76*c2e0c6b5SAndroid Build Coastguard Worker   n = id_alloc(a, sizeof(struct id_entry) + len);
77*c2e0c6b5SAndroid Build Coastguard Worker   n->id12 = id12;
78*c2e0c6b5SAndroid Build Coastguard Worker   n->id34 = id34;
79*c2e0c6b5SAndroid Build Coastguard Worker   n->cat = cat;
80*c2e0c6b5SAndroid Build Coastguard Worker   n->src = src;
81*c2e0c6b5SAndroid Build Coastguard Worker   memcpy(n->name, text, len+1);
82*c2e0c6b5SAndroid Build Coastguard Worker   n->next = a->id_hash[h];
83*c2e0c6b5SAndroid Build Coastguard Worker   a->id_hash[h] = n;
84*c2e0c6b5SAndroid Build Coastguard Worker   return 0;
85*c2e0c6b5SAndroid Build Coastguard Worker }
86*c2e0c6b5SAndroid Build Coastguard Worker 
87*c2e0c6b5SAndroid Build Coastguard Worker char
pci_id_lookup(struct pci_access * a,int flags,int cat,int id1,int id2,int id3,int id4)88*c2e0c6b5SAndroid Build Coastguard Worker *pci_id_lookup(struct pci_access *a, int flags, int cat, int id1, int id2, int id3, int id4)
89*c2e0c6b5SAndroid Build Coastguard Worker {
90*c2e0c6b5SAndroid Build Coastguard Worker   struct id_entry *n, *best;
91*c2e0c6b5SAndroid Build Coastguard Worker   u32 id12 = id_pair(id1, id2);
92*c2e0c6b5SAndroid Build Coastguard Worker   u32 id34 = id_pair(id3, id4);
93*c2e0c6b5SAndroid Build Coastguard Worker 
94*c2e0c6b5SAndroid Build Coastguard Worker   if (a->id_hash)
95*c2e0c6b5SAndroid Build Coastguard Worker     {
96*c2e0c6b5SAndroid Build Coastguard Worker       n = a->id_hash[id_hash(cat, id12, id34)];
97*c2e0c6b5SAndroid Build Coastguard Worker       best = NULL;
98*c2e0c6b5SAndroid Build Coastguard Worker       for (; n; n=n->next)
99*c2e0c6b5SAndroid Build Coastguard Worker         {
100*c2e0c6b5SAndroid Build Coastguard Worker 	  if (n->id12 != id12 || n->id34 != id34 || n->cat != cat)
101*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
102*c2e0c6b5SAndroid Build Coastguard Worker 	  if (n->src == SRC_LOCAL && (flags & PCI_LOOKUP_SKIP_LOCAL))
103*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
104*c2e0c6b5SAndroid Build Coastguard Worker 	  if (n->src == SRC_NET && !(flags & PCI_LOOKUP_NETWORK))
105*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
106*c2e0c6b5SAndroid Build Coastguard Worker 	  if (n->src == SRC_CACHE && !(flags & PCI_LOOKUP_CACHE))
107*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
108*c2e0c6b5SAndroid Build Coastguard Worker 	  if (n->src == SRC_HWDB && (flags & (PCI_LOOKUP_SKIP_LOCAL | PCI_LOOKUP_NO_HWDB)))
109*c2e0c6b5SAndroid Build Coastguard Worker 	    continue;
110*c2e0c6b5SAndroid Build Coastguard Worker 	  if (!best || best->src < n->src)
111*c2e0c6b5SAndroid Build Coastguard Worker 	    best = n;
112*c2e0c6b5SAndroid Build Coastguard Worker 	}
113*c2e0c6b5SAndroid Build Coastguard Worker       if (best)
114*c2e0c6b5SAndroid Build Coastguard Worker 	return best->name;
115*c2e0c6b5SAndroid Build Coastguard Worker     }
116*c2e0c6b5SAndroid Build Coastguard Worker   return NULL;
117*c2e0c6b5SAndroid Build Coastguard Worker }
118*c2e0c6b5SAndroid Build Coastguard Worker 
119*c2e0c6b5SAndroid Build Coastguard Worker void
pci_id_hash_free(struct pci_access * a)120*c2e0c6b5SAndroid Build Coastguard Worker pci_id_hash_free(struct pci_access *a)
121*c2e0c6b5SAndroid Build Coastguard Worker {
122*c2e0c6b5SAndroid Build Coastguard Worker   pci_mfree(a->id_hash);
123*c2e0c6b5SAndroid Build Coastguard Worker   a->id_hash = NULL;
124*c2e0c6b5SAndroid Build Coastguard Worker   while (a->current_id_bucket)
125*c2e0c6b5SAndroid Build Coastguard Worker     {
126*c2e0c6b5SAndroid Build Coastguard Worker       struct id_bucket *buck = a->current_id_bucket;
127*c2e0c6b5SAndroid Build Coastguard Worker       a->current_id_bucket = buck->next;
128*c2e0c6b5SAndroid Build Coastguard Worker       pci_mfree(buck);
129*c2e0c6b5SAndroid Build Coastguard Worker     }
130*c2e0c6b5SAndroid Build Coastguard Worker }
131