Subversion Repositories HelenOS-historic

Rev

Rev 1301 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1301 Rev 1302
Line 16... Line 16...
16
 
16
 
17
#include "internal.h"
17
#include "internal.h"
18
#include "pci_ids.h"
18
#include "pci_ids.h"
19
 
19
 
20
struct id_entry {
20
struct id_entry {
21
  struct id_entry *next;
21
    struct id_entry *next;
22
  u32 id12, id34;
22
    u32 id12, id34;
23
  byte cat;
23
    byte cat;
24
  byte name[1];
24
    byte name[1];
25
};
25
};
26
 
26
 
27
enum id_entry_type {
27
enum id_entry_type {
28
  ID_UNKNOWN,
28
    ID_UNKNOWN,
29
  ID_VENDOR,
29
    ID_VENDOR,
30
  ID_DEVICE,
30
    ID_DEVICE,
31
  ID_SUBSYSTEM,
31
    ID_SUBSYSTEM,
32
  ID_GEN_SUBSYSTEM,
32
    ID_GEN_SUBSYSTEM,
33
  ID_CLASS,
33
    ID_CLASS,
34
  ID_SUBCLASS,
34
    ID_SUBCLASS,
35
  ID_PROGIF
35
    ID_PROGIF
36
};
36
};
37
 
37
 
38
struct id_bucket {
38
struct id_bucket {
39
  struct id_bucket *next;
39
    struct id_bucket *next;
40
  unsigned int full;
40
    unsigned int full;
41
};
41
};
42
 
42
 
43
#define MAX_LINE 1024
43
#define MAX_LINE 1024
44
#define BUCKET_SIZE 8192
44
#define BUCKET_SIZE 8192
45
#define HASH_SIZE 4099
45
#define HASH_SIZE 4099
46
 
46
 
47
#ifdef __GNUC__
47
#ifdef __GNUC__
48
#define BUCKET_ALIGNMENT __alignof__(struct id_bucket)
48
#define BUCKET_ALIGNMENT __alignof__(struct id_bucket)
49
#else
49
#else
50
union id_align {
50
union id_align {
51
  struct id_bucket *next;
51
    struct id_bucket *next;
52
  unsigned int full;
52
    unsigned int full;
53
};
53
};
54
#define BUCKET_ALIGNMENT sizeof(union id_align)
54
#define BUCKET_ALIGNMENT sizeof(union id_align)
55
#endif
55
#endif
56
#define BUCKET_ALIGN(n) ((n)+BUCKET_ALIGNMENT-(n)%BUCKET_ALIGNMENT)
56
#define BUCKET_ALIGN(n) ((n)+BUCKET_ALIGNMENT-(n)%BUCKET_ALIGNMENT)
57
 
57
 
58
static void *id_alloc(struct pci_access *a, unsigned int size)
58
static void *id_alloc(struct pci_access *a, unsigned int size)
59
{
59
{
60
  struct id_bucket *buck = a->current_id_bucket;
60
    struct id_bucket *buck = a->current_id_bucket;
61
  unsigned int pos;
61
    unsigned int pos;
62
  if (!buck || buck->full + size > BUCKET_SIZE)
62
    if (!buck || buck->full + size > BUCKET_SIZE) {
63
    {
-
 
64
      buck = pci_malloc(a, BUCKET_SIZE);
63
        buck = pci_malloc(a, BUCKET_SIZE);
65
      buck->next = a->current_id_bucket;
64
        buck->next = a->current_id_bucket;
66
      a->current_id_bucket = buck;
65
        a->current_id_bucket = buck;
67
      buck->full = BUCKET_ALIGN(sizeof(struct id_bucket));
66
        buck->full = BUCKET_ALIGN(sizeof(struct id_bucket));
68
    }
67
    }
69
  pos = buck->full;
68
    pos = buck->full;
70
  buck->full = BUCKET_ALIGN(buck->full + size);
69
    buck->full = BUCKET_ALIGN(buck->full + size);
71
  return (byte *)buck + pos;
70
    return (byte *) buck + pos;
72
}
71
}
73
 
72
 
74
static inline u32 id_pair(unsigned int x, unsigned int y)
73
static inline u32 id_pair(unsigned int x, unsigned int y)
75
{
74
{
76
  return ((x << 16) | y);
75
    return ((x << 16) | y);
77
}
76
}
78
 
77
 
79
static inline unsigned int id_hash(int cat, u32 id12, u32 id34)
78
static inline unsigned int id_hash(int cat, u32 id12, u32 id34)
80
{
79
{
81
  unsigned int h;
80
    unsigned int h;
82
 
81
 
83
  h = id12 ^ (id34 << 3) ^ (cat << 5);
82
    h = id12 ^ (id34 << 3) ^ (cat << 5);
84
  return h % HASH_SIZE;
83
    return h % HASH_SIZE;
85
}
84
}
86
 
85
 
87
static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4)
86
static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1,
-
 
87
                  int id2, int id3, int id4)
88
{
88
{
89
  struct id_entry *n;
89
    struct id_entry *n;
90
  u32 id12 = id_pair(id1, id2);
90
    u32 id12 = id_pair(id1, id2);
91
  u32 id34 = id_pair(id3, id4);
91
    u32 id34 = id_pair(id3, id4);
92
 
92
 
93
  n = a->id_hash[id_hash(cat, id12, id34)];
93
    n = a->id_hash[id_hash(cat, id12, id34)];
94
  while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat))
94
    while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat))
95
    n = n->next;
95
        n = n->next;
96
  return n;
96
    return n;
97
}
97
}
98
 
98
 
99
static int id_insert(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text)
99
static int id_insert(struct pci_access *a, int cat, int id1, int id2,
-
 
100
             int id3, int id4, byte * text)
100
{
101
{
101
  u32 id12 = id_pair(id1, id2);
102
    u32 id12 = id_pair(id1, id2);
102
  u32 id34 = id_pair(id3, id4);
103
    u32 id34 = id_pair(id3, id4);
103
  unsigned int h = id_hash(cat, id12, id34);
104
    unsigned int h = id_hash(cat, id12, id34);
104
  struct id_entry *n = a->id_hash[h];
105
    struct id_entry *n = a->id_hash[h];
105
  int len = strlen((char *) text);
106
    int len = strlen((char *) text);
106
 
107
 
107
  while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat))
108
    while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat))
108
    n = n->next;
109
        n = n->next;
109
  if (n)
110
    if (n)
110
    return 1;
111
        return 1;
111
  n = id_alloc(a, sizeof(struct id_entry) + len);
112
    n = id_alloc(a, sizeof(struct id_entry) + len);
112
  n->id12 = id12;
113
    n->id12 = id12;
113
  n->id34 = id34;
114
    n->id34 = id34;
114
  n->cat = cat;
115
    n->cat = cat;
115
  memcpy(n->name, text, len+1);
116
    memcpy(n->name, text, len + 1);
116
  n->next = a->id_hash[h];
117
    n->next = a->id_hash[h];
117
  a->id_hash[h] = n;
118
    a->id_hash[h] = n;
118
  return 0;
119
    return 0;
119
}
120
}
120
 
121
 
121
static int id_hex(byte *p, int cnt)
122
static int id_hex(byte * p, int cnt)
122
{
123
{
123
  int x = 0;
124
    int x = 0;
124
  while (cnt--)
125
    while (cnt--) {
125
    {
-
 
126
      x <<= 4;
126
        x <<= 4;
127
      if (*p >= '0' && *p <= '9')
127
        if (*p >= '0' && *p <= '9')
128
    x += (*p - '0');
128
            x += (*p - '0');
129
      else if (*p >= 'a' && *p <= 'f')
129
        else if (*p >= 'a' && *p <= 'f')
130
    x += (*p - 'a' + 10);
130
            x += (*p - 'a' + 10);
131
      else if (*p >= 'A' && *p <= 'F')
131
        else if (*p >= 'A' && *p <= 'F')
132
    x += (*p - 'A' + 10);
132
            x += (*p - 'A' + 10);
133
      else
133
        else
134
    return -1;
134
            return -1;
135
      p++;
135
        p++;
136
    }
136
    }
137
  return x;
137
    return x;
138
}
138
}
139
 
139
 
140
static inline int id_white_p(int c)
140
static inline int id_white_p(int c)
141
{
141
{
142
  return (c == ' ') || (c == '\t');
142
    return (c == ' ') || (c == '\t');
143
}
143
}
144
 
144
 
145
static const char *id_parse_list(struct pci_access *a, int *lino)
145
static const char *id_parse_list(struct pci_access *a, int *lino)
146
{
146
{
147
  byte *line;
147
    byte *line;
148
  byte *p;
148
    byte *p;
149
  int id1=0, id2=0, id3=0, id4=0;
149
    int id1 = 0, id2 = 0, id3 = 0, id4 = 0;
150
  int cat = -1;
150
    int cat = -1;
151
  int nest;
151
    int nest;
152
  static const char parse_error[] = "Parse error";
152
    static const char parse_error[] = "Parse error";
153
  int i;
153
    int i;
154
 
154
 
155
  *lino = 0;
155
    *lino = 0;
156
  for (i = 0; i < sizeof(pci_ids)/sizeof(char *); i++) {
156
    for (i = 0; i < sizeof(pci_ids) / sizeof(char *); i++) {
157
      line = (byte *) pci_ids[i];
157
        line = (byte *) pci_ids[i];
158
      (*lino)++;
158
        (*lino)++;
159
      p = line;
159
        p = line;
160
      while (*p)
160
        while (*p)
161
    p++;
161
            p++;
162
      if (p > line && (p[-1] == ' ' || p[-1] == '\t'))
162
        if (p > line && (p[-1] == ' ' || p[-1] == '\t'))
163
    *--p = 0;
163
            *--p = 0;
164
 
164
 
165
      p = line;
165
        p = line;
166
      while (id_white_p(*p))
166
        while (id_white_p(*p))
167
    p++;
167
            p++;
168
      if (!*p || *p == '#')
168
        if (!*p || *p == '#')
169
    continue;
169
            continue;
170
 
170
 
171
      p = line;
171
        p = line;
172
      while (*p == '\t')
172
        while (*p == '\t')
173
    p++;
173
            p++;
174
      nest = p - line;
174
        nest = p - line;
175
 
175
 
176
      if (!nest)                    /* Top-level entries */
176
        if (!nest) {    /* Top-level entries */
177
    {
-
 
178
      if (p[0] == 'C' && p[1] == ' ')       /* Class block */
177
            if (p[0] == 'C' && p[1] == ' ') {   /* Class block */
179
        {
178
                if ((id1 = id_hex(p + 2, 2)) < 0
180
          if ((id1 = id_hex(p+2, 2)) < 0 || !id_white_p(p[4]))
179
                    || !id_white_p(p[4]))
181
        return parse_error;
180
                    return parse_error;
182
          cat = ID_CLASS;
181
                cat = ID_CLASS;
183
          p += 5;
182
                p += 5;
184
        }
-
 
185
      else if (p[0] == 'S' && p[1] == ' ')
183
            } else if (p[0] == 'S' && p[1] == ' ') {    /* Generic subsystem block */
186
        {                       /* Generic subsystem block */
-
 
187
          if ((id1 = id_hex(p+2, 4)) < 0 || p[6])
184
                if ((id1 = id_hex(p + 2, 4)) < 0 || p[6])
188
        return parse_error;
185
                    return parse_error;
189
          if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0))
186
                if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0))
190
        return "Vendor does not exist";
187
                    return "Vendor does not exist";
191
          cat = ID_GEN_SUBSYSTEM;
188
                cat = ID_GEN_SUBSYSTEM;
-
 
189
                continue;
-
 
190
            } else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ') { /* Unrecognized block (RFU) */
-
 
191
                cat = ID_UNKNOWN;
192
          continue;
192
                continue;
-
 
193
            } else {    /* Vendor ID */
-
 
194
 
-
 
195
                if ((id1 = id_hex(p, 4)) < 0
-
 
196
                    || !id_white_p(p[4]))
-
 
197
                    return parse_error;
-
 
198
                cat = ID_VENDOR;
-
 
199
                p += 5;
193
        }
200
            }
-
 
201
            id2 = id3 = id4 = 0;
-
 
202
        } else if (cat == ID_UNKNOWN)   /* Nested entries in RFU blocks are skipped */
-
 
203
            continue;
194
      else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ')
204
        else if (nest == 1) /* Nesting level 1 */
-
 
205
            switch (cat) {
-
 
206
            case ID_VENDOR:
-
 
207
            case ID_DEVICE:
-
 
208
            case ID_SUBSYSTEM:
195
        {                       /* Unrecognized block (RFU) */
209
                if ((id2 = id_hex(p, 4)) < 0
-
 
210
                    || !id_white_p(p[4]))
-
 
211
                    return parse_error;
-
 
212
                p += 5;
196
          cat = ID_UNKNOWN;
213
                cat = ID_DEVICE;
197
          continue;
214
                id3 = id4 = 0;
-
 
215
                break;
-
 
216
            case ID_GEN_SUBSYSTEM:
-
 
217
                if ((id2 = id_hex(p, 4)) < 0
-
 
218
                    || !id_white_p(p[4]))
-
 
219
                    return parse_error;
198
        }
220
                p += 5;
199
      else                      /* Vendor ID */
221
                id3 = id4 = 0;
-
 
222
                break;
-
 
223
            case ID_CLASS:
-
 
224
            case ID_SUBCLASS:
-
 
225
            case ID_PROGIF:
-
 
226
                if ((id2 = id_hex(p, 2)) < 0
-
 
227
                    || !id_white_p(p[2]))
-
 
228
                    return parse_error;
200
        {
229
                p += 3;
-
 
230
                cat = ID_SUBCLASS;
-
 
231
                id3 = id4 = 0;
-
 
232
                break;
-
 
233
            default:
-
 
234
                return parse_error;
-
 
235
        } else if (nest == 2)   /* Nesting level 2 */
-
 
236
            switch (cat) {
-
 
237
            case ID_DEVICE:
-
 
238
            case ID_SUBSYSTEM:
201
          if ((id1 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
239
                if ((id3 = id_hex(p, 4)) < 0
-
 
240
                    || !id_white_p(p[4])
-
 
241
                    || (id4 = id_hex(p + 5, 4)) < 0
-
 
242
                    || !id_white_p(p[9]))
202
        return parse_error;
243
                    return parse_error;
-
 
244
                p += 10;
203
          cat = ID_VENDOR;
245
                cat = ID_SUBSYSTEM;
-
 
246
                break;
-
 
247
            case ID_CLASS:
-
 
248
            case ID_SUBCLASS:
-
 
249
            case ID_PROGIF:
-
 
250
                if ((id3 = id_hex(p, 2)) < 0
-
 
251
                    || !id_white_p(p[2]))
-
 
252
                    return parse_error;
204
          p += 5;
253
                p += 3;
-
 
254
                cat = ID_PROGIF;
-
 
255
                id4 = 0;
-
 
256
                break;
-
 
257
            default:
-
 
258
                return parse_error;
-
 
259
        } else      /* Nesting level 3 or more */
-
 
260
            return parse_error;
-
 
261
        while (id_white_p(*p))
205
        }
262
            p++;
-
 
263
        if (!*p)
206
      id2 = id3 = id4 = 0;
264
            return parse_error;
-
 
265
        if (id_insert(a, cat, id1, id2, id3, id4, p))
-
 
266
            return "Duplicate entry";
207
    }
267
    }
208
      else if (cat == ID_UNKNOWN)           /* Nested entries in RFU blocks are skipped */
-
 
209
    continue;
-
 
210
      else if (nest == 1)               /* Nesting level 1 */
-
 
211
    switch (cat)
-
 
212
      {
-
 
213
      case ID_VENDOR:
-
 
214
      case ID_DEVICE:
-
 
215
      case ID_SUBSYSTEM:
-
 
216
        if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
-
 
217
          return parse_error;
-
 
218
        p += 5;
-
 
219
        cat = ID_DEVICE;
-
 
220
        id3 = id4 = 0;
-
 
221
        break;
-
 
222
      case ID_GEN_SUBSYSTEM:
-
 
223
        if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
-
 
224
          return parse_error;
-
 
225
        p += 5;
-
 
226
        id3 = id4 = 0;
-
 
227
        break;
-
 
228
      case ID_CLASS:
-
 
229
      case ID_SUBCLASS:
-
 
230
      case ID_PROGIF:
-
 
231
        if ((id2 = id_hex(p, 2)) < 0 || !id_white_p(p[2]))
-
 
232
          return parse_error;
-
 
233
        p += 3;
-
 
234
        cat = ID_SUBCLASS;
-
 
235
        id3 = id4 = 0;
-
 
236
        break;
-
 
237
      default:
-
 
238
        return parse_error;
-
 
239
      }
-
 
240
      else if (nest == 2)               /* Nesting level 2 */
-
 
241
    switch (cat)
-
 
242
      {
-
 
243
      case ID_DEVICE:
-
 
244
      case ID_SUBSYSTEM:
-
 
245
        if ((id3 = id_hex(p, 4)) < 0 || !id_white_p(p[4]) || (id4 = id_hex(p+5, 4)) < 0 || !id_white_p(p[9]))
-
 
246
          return parse_error;
-
 
247
        p += 10;
-
 
248
        cat = ID_SUBSYSTEM;
-
 
249
        break;
-
 
250
      case ID_CLASS:
-
 
251
      case ID_SUBCLASS:
-
 
252
      case ID_PROGIF:
-
 
253
        if ((id3 = id_hex(p, 2)) < 0 || !id_white_p(p[2]))
-
 
254
          return parse_error;
-
 
255
        p += 3;
-
 
256
        cat = ID_PROGIF;
-
 
257
        id4 = 0;
-
 
258
        break;
-
 
259
      default:
-
 
260
        return parse_error;
-
 
261
      }
-
 
262
      else                      /* Nesting level 3 or more */
-
 
263
    return parse_error;
-
 
264
      while (id_white_p(*p))
-
 
265
    p++;
-
 
266
      if (!*p)
-
 
267
    return parse_error;
-
 
268
      if (id_insert(a, cat, id1, id2, id3, id4, p))
-
 
269
    return "Duplicate entry";
-
 
270
    }
-
 
271
  return NULL;
-
 
272
}
-
 
273
 
-
 
274
int
-
 
275
pci_load_name_list(struct pci_access *a)
-
 
276
{
-
 
277
  int lino;
-
 
278
  const char *err;
-
 
279
 
-
 
280
  pci_free_name_list(a);
-
 
281
  a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE);
-
 
282
  bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE);
-
 
283
  err = id_parse_list(a, &lino);
-
 
284
  if (err)
-
 
285
    a->error("%s at %s, element %d\n", err, "pci_ids.h", lino);
-
 
286
  return 1;
-
 
287
}
-
 
288
 
-
 
289
void
-
 
290
pci_free_name_list(struct pci_access *a)
-
 
291
{
-
 
292
  pci_mfree(a->id_hash);
-
 
293
  a->id_hash = NULL;
-
 
294
  while (a->current_id_bucket)
-
 
295
    {
-
 
296
      struct id_bucket *buck = a->current_id_bucket;
-
 
297
      a->current_id_bucket = buck->next;
-
 
298
      pci_mfree(buck);
-
 
299
    }
-
 
300
}
-
 
301
 
-
 
302
static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, int id, int isv, int isd)
-
 
303
{
-
 
304
  struct id_entry *d = NULL;
-
 
305
  if (iv > 0 && id > 0)                     /* Per-device lookup */
-
 
306
    d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd);
-
 
307
  if (!d)                           /* Generic lookup */
-
 
308
    d = id_lookup(a, ID_GEN_SUBSYSTEM, isv, isd, 0, 0);
-
 
309
  if (!d && iv == isv && id == isd)             /* Check for subsystem == device */
-
 
310
    d = id_lookup(a, ID_DEVICE, iv, id, 0, 0);
-
 
311
  return d;
-
 
312
}
-
 
313
 
-
 
314
char *
-
 
315
pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...)
-
 
316
{
-
 
317
  va_list args;
-
 
318
  int num, res, synth;
-
 
319
  struct id_entry *v, *d, *cls, *pif;
-
 
320
  int iv, id, isv, isd, icls, ipif;
-
 
321
 
-
 
322
  va_start(args, flags);
-
 
323
 
-
 
324
  num = 0;
-
 
325
  if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids)
-
 
326
    {
-
 
327
      flags &= ~PCI_LOOKUP_NUMERIC;
-
 
328
      num = 1;
-
 
329
    }
-
 
330
  else if (!a->id_hash)
-
 
331
    {
-
 
332
      if (!pci_load_name_list(a))
-
 
333
    num = a->numeric_ids = 1;
-
 
334
    }
-
 
335
 
-
 
336
  if (flags & PCI_LOOKUP_NO_NUMBERS)
-
 
337
    {
-
 
338
      flags &= ~PCI_LOOKUP_NO_NUMBERS;
-
 
339
      synth = 0;
-
 
340
      if (num)
-
 
341
    return NULL;
268
    return NULL;
342
    }
269
}
343
  else
-
 
344
    synth = 1;
-
 
345
 
270
 
346
  switch (flags)
271
int pci_load_name_list(struct pci_access *a)
347
    {
272
{
348
    case PCI_LOOKUP_VENDOR:
-
 
349
      iv = va_arg(args, int);
-
 
350
      if (num)
273
    int lino;
351
    res = snprintf(buf, size, "%04x", iv);
-
 
352
      else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0))
-
 
353
    return (char *) v->name;
274
    const char *err;
-
 
275
 
354
      else
276
    pci_free_name_list(a);
355
    res = snprintf(buf, size, "Unknown vendor %04x", iv);
277
    a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE);
356
      break;
-
 
357
    case PCI_LOOKUP_DEVICE:
-
 
358
      iv = va_arg(args, int);
278
    bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE);
359
      id = va_arg(args, int);
279
    err = id_parse_list(a, &lino);
360
      if (num)
280
    if (err)
361
    res = snprintf(buf, size, "%04x", id);
-
 
362
      else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0))
-
 
363
    return (char *) d->name;
-
 
364
      else if (synth)
-
 
365
    res = snprintf(buf, size, "Unknown device %04x", id);
281
        a->error("%s at %s, element %d\n", err, "pci_ids.h", lino);
366
      else
-
 
367
    return NULL;
282
    return 1;
368
      break;
283
}
369
    case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE:
-
 
370
      iv = va_arg(args, int);
-
 
371
      id = va_arg(args, int);
-
 
372
      if (num)
284
 
373
    res = snprintf(buf, size, "%04x:%04x", iv, id);
285
void pci_free_name_list(struct pci_access *a)
374
      else
-
 
375
    {
286
{
376
      v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0);
287
    pci_mfree(a->id_hash);
377
      d = id_lookup(a, ID_DEVICE, iv, id, 0, 0);
288
    a->id_hash = NULL;
378
      if (v && d)
289
    while (a->current_id_bucket) {
379
        res = snprintf(buf, size, "%s %s", v->name, d->name);
290
        struct id_bucket *buck = a->current_id_bucket;
380
      else if (!synth)
-
 
381
        return NULL;
291
        a->current_id_bucket = buck->next;
382
      else if (!v)
292
        pci_mfree(buck);
383
        res = snprintf(buf, size, "Unknown device %04x:%04x", iv, id);
-
 
384
      else  /* !d */
-
 
385
        res = snprintf(buf, size, "%s Unknown device %04x", v->name, id);
-
 
386
    }
293
    }
387
      break;
294
}
388
    case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR:
-
 
389
      isv = va_arg(args, int);
-
 
390
      if (num)
295
 
391
    res = snprintf(buf, size, "%04x", isv);
-
 
392
      else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0))
296
static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv,
393
    return (char *) v->name;
-
 
394
      else if (synth)
297
                     int id, int isv, int isd)
395
    res = snprintf(buf, size, "Unknown vendor %04x", isv);
-
 
396
      else
298
{
397
    return NULL;
299
    struct id_entry *d = NULL;
398
      break;
-
 
399
    case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE:
-
 
400
      iv = va_arg(args, int);
300
    if (iv > 0 && id > 0)   /* Per-device lookup */
401
      id = va_arg(args, int);
301
        d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd);
402
      isv = va_arg(args, int);
302
    if (!d)         /* Generic lookup */
403
      isd = va_arg(args, int);
303
        d = id_lookup(a, ID_GEN_SUBSYSTEM, isv, isd, 0, 0);
404
      if (num)
-
 
405
    res = snprintf(buf, size, "%04x", isd);
304
    if (!d && iv == isv && id == isd)   /* Check for subsystem == device */
406
      else if (d = id_lookup_subsys(a, iv, id, isv, isd))
305
        d = id_lookup(a, ID_DEVICE, iv, id, 0, 0);
407
    return (char *) d->name;
306
    return d;
408
      else if (synth)
-
 
-
 
307
}
-
 
308
 
409
    res = snprintf(buf, size, "Unknown device %04x", isd);
309
char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags,
410
      else
310
              ...)
411
    return NULL;
311
{
412
      break;
312
    va_list args;
413
    case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
-
 
414
      iv = va_arg(args, int);
313
    int num, res, synth;
415
      id = va_arg(args, int);
314
    struct id_entry *v, *d, *cls, *pif;
416
      isv = va_arg(args, int);
315
    int iv, id, isv, isd, icls, ipif;
-
 
316
 
417
      isd = va_arg(args, int);
317
    va_start(args, flags);
418
      if (num)
-
 
419
    res = snprintf(buf, size, "%04x:%04x", isv, isd);
-
 
420
      else
-
 
421
    {
318
 
422
      v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0);
-
 
423
      d = id_lookup_subsys(a, iv, id, isv, isd);
-
 
424
      if (v && d)
319
    num = 0;
425
        res = snprintf(buf, size, "%s %s", v->name, d->name);
320
    if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids) {
426
      else if (!synth)
321
        flags &= ~PCI_LOOKUP_NUMERIC;
427
        return NULL;
322
        num = 1;
428
      else if (!v)
323
    } else if (!a->id_hash) {
429
        res = snprintf(buf, size, "Unknown device %04x:%04x", isv, isd);
324
        if (!pci_load_name_list(a))
430
      else /* !d */
325
            num = a->numeric_ids = 1;
431
        res = snprintf(buf, size, "%s Unknown device %04x", v->name, isd);
-
 
432
    }
326
    }
-
 
327
 
-
 
328
    if (flags & PCI_LOOKUP_NO_NUMBERS) {
-
 
329
        flags &= ~PCI_LOOKUP_NO_NUMBERS;
-
 
330
        synth = 0;
-
 
331
        if (num)
-
 
332
            return NULL;
-
 
333
    } else
-
 
334
        synth = 1;
-
 
335
 
-
 
336
    switch (flags) {
-
 
337
    case PCI_LOOKUP_VENDOR:
-
 
338
        iv = va_arg(args, int);
-
 
339
        if (num)
-
 
340
            res = snprintf(buf, size, "%04x", iv);
-
 
341
        else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0))
-
 
342
            return (char *) v->name;
-
 
343
        else
-
 
344
            res =
-
 
345
                snprintf(buf, size, "Unknown vendor %04x", iv);
-
 
346
        break;
-
 
347
    case PCI_LOOKUP_DEVICE:
-
 
348
        iv = va_arg(args, int);
-
 
349
        id = va_arg(args, int);
-
 
350
        if (num)
-
 
351
            res = snprintf(buf, size, "%04x", id);
-
 
352
        else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0))
-
 
353
            return (char *) d->name;
-
 
354
        else if (synth)
-
 
355
            res =
-
 
356
                snprintf(buf, size, "Unknown device %04x", id);
-
 
357
        else
-
 
358
            return NULL;
-
 
359
        break;
-
 
360
    case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE:
-
 
361
        iv = va_arg(args, int);
-
 
362
        id = va_arg(args, int);
-
 
363
        if (num)
-
 
364
            res = snprintf(buf, size, "%04x:%04x", iv, id);
-
 
365
        else {
-
 
366
            v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0);
-
 
367
            d = id_lookup(a, ID_DEVICE, iv, id, 0, 0);
-
 
368
            if (v && d)
-
 
369
                res =
-
 
370
                    snprintf(buf, size, "%s %s", v->name,
-
 
371
                         d->name);
-
 
372
            else if (!synth)
-
 
373
                return NULL;
-
 
374
            else if (!v)
-
 
375
                res =
-
 
376
                    snprintf(buf, size,
-
 
377
                         "Unknown device %04x:%04x",
-
 
378
                         iv, id);
-
 
379
            else    /* !d */
-
 
380
                res =
-
 
381
                    snprintf(buf, size,
-
 
382
                         "%s Unknown device %04x",
-
 
383
                         v->name, id);
-
 
384
        }
-
 
385
        break;
-
 
386
    case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR:
-
 
387
        isv = va_arg(args, int);
-
 
388
        if (num)
-
 
389
            res = snprintf(buf, size, "%04x", isv);
-
 
390
        else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0))
-
 
391
            return (char *) v->name;
-
 
392
        else if (synth)
-
 
393
            res =
-
 
394
                snprintf(buf, size, "Unknown vendor %04x",
-
 
395
                     isv);
-
 
396
        else
-
 
397
            return NULL;
-
 
398
        break;
-
 
399
    case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE:
-
 
400
        iv = va_arg(args, int);
-
 
401
        id = va_arg(args, int);
-
 
402
        isv = va_arg(args, int);
-
 
403
        isd = va_arg(args, int);
-
 
404
        if (num)
-
 
405
            res = snprintf(buf, size, "%04x", isd);
-
 
406
        else if (d = id_lookup_subsys(a, iv, id, isv, isd))
-
 
407
            return (char *) d->name;
-
 
408
        else if (synth)
-
 
409
            res =
-
 
410
                snprintf(buf, size, "Unknown device %04x",
-
 
411
                     isd);
-
 
412
        else
-
 
413
            return NULL;
-
 
414
        break;
-
 
415
    case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
-
 
416
        iv = va_arg(args, int);
-
 
417
        id = va_arg(args, int);
-
 
418
        isv = va_arg(args, int);
-
 
419
        isd = va_arg(args, int);
-
 
420
        if (num)
-
 
421
            res = snprintf(buf, size, "%04x:%04x", isv, isd);
-
 
422
        else {
-
 
423
            v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0);
-
 
424
            d = id_lookup_subsys(a, iv, id, isv, isd);
-
 
425
            if (v && d)
-
 
426
                res =
-
 
427
                    snprintf(buf, size, "%s %s", v->name,
-
 
428
                         d->name);
-
 
429
            else if (!synth)
-
 
430
                return NULL;
-
 
431
            else if (!v)
-
 
432
                res =
-
 
433
                    snprintf(buf, size,
-
 
434
                         "Unknown device %04x:%04x",
-
 
435
                         isv, isd);
-
 
436
            else    /* !d */
-
 
437
                res =
-
 
438
                    snprintf(buf, size,
-
 
439
                         "%s Unknown device %04x",
-
 
440
                         v->name, isd);
-
 
441
        }
433
      break;
442
        break;
434
    case PCI_LOOKUP_CLASS:
443
    case PCI_LOOKUP_CLASS:
435
      icls = va_arg(args, int);
444
        icls = va_arg(args, int);
436
      if (num)
445
        if (num)
437
    res = snprintf(buf, size, "%04x", icls);
446
            res = snprintf(buf, size, "%04x", icls);
-
 
447
        else if (cls =
438
      else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0))
448
             id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff,
-
 
449
                   0, 0))
439
    return (char *) cls->name;
450
            return (char *) cls->name;
440
      else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0))
451
        else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0))
-
 
452
            res =
441
    res = snprintf(buf, size, "%s [%04x]", cls->name, icls);
453
                snprintf(buf, size, "%s [%04x]", cls->name,
-
 
454
                     icls);
442
      else if (synth)
455
        else if (synth)
443
    res = snprintf(buf, size, "Class %04x", icls);
456
            res = snprintf(buf, size, "Class %04x", icls);
444
      else
457
        else
445
    return NULL;
458
            return NULL;
446
      break;
459
        break;
447
    case PCI_LOOKUP_PROGIF:
460
    case PCI_LOOKUP_PROGIF:
448
      icls = va_arg(args, int);
461
        icls = va_arg(args, int);
449
      ipif = va_arg(args, int);
462
        ipif = va_arg(args, int);
450
      if (num)
463
        if (num)
451
    res = snprintf(buf, size, "%02x", ipif);
464
            res = snprintf(buf, size, "%02x", ipif);
-
 
465
        else if (pif =
452
      else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0))
466
             id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff,
-
 
467
                   ipif, 0))
453
    return (char *) pif->name;
468
            return (char *) pif->name;
454
      else if (icls == 0x0101 && !(ipif & 0x70))
469
        else if (icls == 0x0101 && !(ipif & 0x70)) {
455
    {
-
 
456
      /* IDE controllers have complex prog-if semantics */
470
            /* IDE controllers have complex prog-if semantics */
457
      res = snprintf(buf, size, "%s%s%s%s%s",
471
            res = snprintf(buf, size, "%s%s%s%s%s",
458
             (ipif & 0x80) ? "Master " : "",
472
                       (ipif & 0x80) ? "Master " : "",
459
             (ipif & 0x08) ? "SecP " : "",
473
                       (ipif & 0x08) ? "SecP " : "",
460
             (ipif & 0x04) ? "SecO " : "",
474
                       (ipif & 0x04) ? "SecO " : "",
461
             (ipif & 0x02) ? "PriP " : "",
475
                       (ipif & 0x02) ? "PriP " : "",
462
             (ipif & 0x01) ? "PriO " : "");
476
                       (ipif & 0x01) ? "PriO " : "");
463
      if (res > 0 && res < size)
477
            if (res > 0 && res < size)
464
        buf[--res] = 0;
478
                buf[--res] = 0;
-
 
479
        } else if (synth)
-
 
480
            res = snprintf(buf, size, "ProgIf %02x", ipif);
-
 
481
        else
-
 
482
            return NULL;
-
 
483
        break;
-
 
484
    default:
-
 
485
        return "<pci_lookup_name: invalid request>";
465
    }
486
    }
466
      else if (synth)
-
 
467
    res = snprintf(buf, size, "ProgIf %02x", ipif);
-
 
468
      else
-
 
469
    return NULL;
-
 
470
      break;
-
 
471
    default:
-
 
472
      return "<pci_lookup_name: invalid request>";
-
 
473
    }
-
 
474
  if (res < 0 || res >= size)
487
    if (res < 0 || res >= size)
475
    return "<pci_lookup_name: buffer too small>";
488
        return "<pci_lookup_name: buffer too small>";
476
  else
489
    else
477
    return buf;
490
        return buf;
478
}
491
}