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