Changeset 20a9b85 in mainline for pci/libpci/names.c
- Timestamp:
- 2006-05-09T10:55:02Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 46ec2c06
- Parents:
- 4a7c273
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pci/libpci/names.c
r4a7c273 r20a9b85 19 19 20 20 struct id_entry { 21 22 23 24 21 struct id_entry *next; 22 u32 id12, id34; 23 byte cat; 24 byte name[1]; 25 25 }; 26 26 27 27 enum id_entry_type { 28 29 30 31 32 33 34 35 28 ID_UNKNOWN, 29 ID_VENDOR, 30 ID_DEVICE, 31 ID_SUBSYSTEM, 32 ID_GEN_SUBSYSTEM, 33 ID_CLASS, 34 ID_SUBCLASS, 35 ID_PROGIF 36 36 }; 37 37 38 38 struct id_bucket { 39 40 39 struct id_bucket *next; 40 unsigned int full; 41 41 }; 42 42 … … 49 49 #else 50 50 union id_align { 51 52 51 struct id_bucket *next; 52 unsigned int full; 53 53 }; 54 54 #define BUCKET_ALIGNMENT sizeof(union id_align) … … 58 58 static void *id_alloc(struct pci_access *a, unsigned int size) 59 59 { 60 struct id_bucket *buck = a->current_id_bucket; 61 unsigned int pos; 62 if (!buck || buck->full + size > BUCKET_SIZE) 63 { 64 buck = pci_malloc(a, BUCKET_SIZE); 65 buck->next = a->current_id_bucket; 66 a->current_id_bucket = buck; 67 buck->full = BUCKET_ALIGN(sizeof(struct id_bucket)); 68 } 69 pos = buck->full; 70 buck->full = BUCKET_ALIGN(buck->full + size); 71 return (byte *)buck + pos; 60 struct id_bucket *buck = a->current_id_bucket; 61 unsigned int pos; 62 if (!buck || buck->full + size > BUCKET_SIZE) { 63 buck = pci_malloc(a, BUCKET_SIZE); 64 buck->next = a->current_id_bucket; 65 a->current_id_bucket = buck; 66 buck->full = BUCKET_ALIGN(sizeof(struct id_bucket)); 67 } 68 pos = buck->full; 69 buck->full = BUCKET_ALIGN(buck->full + size); 70 return (byte *) buck + pos; 72 71 } 73 72 74 73 static inline u32 id_pair(unsigned int x, unsigned int y) 75 74 { 76 75 return ((x << 16) | y); 77 76 } 78 77 79 78 static inline unsigned int id_hash(int cat, u32 id12, u32 id34) 80 79 { 81 unsigned int h; 82 83 h = id12 ^ (id34 << 3) ^ (cat << 5); 84 return h % HASH_SIZE; 85 } 86 87 static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4) 88 { 89 struct id_entry *n; 90 u32 id12 = id_pair(id1, id2); 91 u32 id34 = id_pair(id3, id4); 92 93 n = a->id_hash[id_hash(cat, id12, id34)]; 94 while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) 95 n = n->next; 96 return n; 97 } 98 99 static int id_insert(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text) 100 { 101 u32 id12 = id_pair(id1, id2); 102 u32 id34 = id_pair(id3, id4); 103 unsigned int h = id_hash(cat, id12, id34); 104 struct id_entry *n = a->id_hash[h]; 105 int len = strlen((char *) text); 106 107 while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) 108 n = n->next; 109 if (n) 110 return 1; 111 n = id_alloc(a, sizeof(struct id_entry) + len); 112 n->id12 = id12; 113 n->id34 = id34; 114 n->cat = cat; 115 memcpy(n->name, text, len+1); 116 n->next = a->id_hash[h]; 117 a->id_hash[h] = n; 118 return 0; 119 } 120 121 static int id_hex(byte *p, int cnt) 122 { 123 int x = 0; 124 while (cnt--) 125 { 126 x <<= 4; 127 if (*p >= '0' && *p <= '9') 128 x += (*p - '0'); 129 else if (*p >= 'a' && *p <= 'f') 130 x += (*p - 'a' + 10); 131 else if (*p >= 'A' && *p <= 'F') 132 x += (*p - 'A' + 10); 133 else 134 return -1; 135 p++; 136 } 137 return x; 80 unsigned int h; 81 82 h = id12 ^ (id34 << 3) ^ (cat << 5); 83 return h % HASH_SIZE; 84 } 85 86 static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, 87 int id2, int id3, int id4) 88 { 89 struct id_entry *n; 90 u32 id12 = id_pair(id1, id2); 91 u32 id34 = id_pair(id3, id4); 92 93 n = a->id_hash[id_hash(cat, id12, id34)]; 94 while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) 95 n = n->next; 96 return n; 97 } 98 99 static int id_insert(struct pci_access *a, int cat, int id1, int id2, 100 int id3, int id4, byte * text) 101 { 102 u32 id12 = id_pair(id1, id2); 103 u32 id34 = id_pair(id3, id4); 104 unsigned int h = id_hash(cat, id12, id34); 105 struct id_entry *n = a->id_hash[h]; 106 int len = strlen((char *) text); 107 108 while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) 109 n = n->next; 110 if (n) 111 return 1; 112 n = id_alloc(a, sizeof(struct id_entry) + len); 113 n->id12 = id12; 114 n->id34 = id34; 115 n->cat = cat; 116 memcpy(n->name, text, len + 1); 117 n->next = a->id_hash[h]; 118 a->id_hash[h] = n; 119 return 0; 120 } 121 122 static int id_hex(byte * p, int cnt) 123 { 124 int x = 0; 125 while (cnt--) { 126 x <<= 4; 127 if (*p >= '0' && *p <= '9') 128 x += (*p - '0'); 129 else if (*p >= 'a' && *p <= 'f') 130 x += (*p - 'a' + 10); 131 else if (*p >= 'A' && *p <= 'F') 132 x += (*p - 'A' + 10); 133 else 134 return -1; 135 p++; 136 } 137 return x; 138 138 } 139 139 140 140 static inline int id_white_p(int c) 141 141 { 142 142 return (c == ' ') || (c == '\t'); 143 143 } 144 144 145 145 static const char *id_parse_list(struct pci_access *a, int *lino) 146 146 { 147 byte *line; 148 byte *p; 149 int id1=0, id2=0, id3=0, id4=0; 150 int cat = -1; 151 int nest; 152 static const char parse_error[] = "Parse error"; 153 int i; 154 155 *lino = 0; 156 for (i = 0; i < sizeof(pci_ids)/sizeof(char *); i++) { 157 line = (byte *) pci_ids[i]; 158 (*lino)++; 159 p = line; 160 while (*p) 161 p++; 162 if (p > line && (p[-1] == ' ' || p[-1] == '\t')) 163 *--p = 0; 164 165 p = line; 166 while (id_white_p(*p)) 167 p++; 168 if (!*p || *p == '#') 169 continue; 170 171 p = line; 172 while (*p == '\t') 173 p++; 174 nest = p - line; 175 176 if (!nest) /* Top-level entries */ 177 { 178 if (p[0] == 'C' && p[1] == ' ') /* Class block */ 179 { 180 if ((id1 = id_hex(p+2, 2)) < 0 || !id_white_p(p[4])) 181 return parse_error; 182 cat = ID_CLASS; 183 p += 5; 184 } 185 else if (p[0] == 'S' && p[1] == ' ') 186 { /* Generic subsystem block */ 187 if ((id1 = id_hex(p+2, 4)) < 0 || p[6]) 188 return parse_error; 189 if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0)) 190 return "Vendor does not exist"; 191 cat = ID_GEN_SUBSYSTEM; 192 continue; 193 } 194 else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ') 195 { /* Unrecognized block (RFU) */ 196 cat = ID_UNKNOWN; 197 continue; 198 } 199 else /* Vendor ID */ 200 { 201 if ((id1 = id_hex(p, 4)) < 0 || !id_white_p(p[4])) 202 return parse_error; 203 cat = ID_VENDOR; 204 p += 5; 205 } 206 id2 = id3 = id4 = 0; 207 } 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) 147 byte *line; 148 byte *p; 149 int id1 = 0, id2 = 0, id3 = 0, id4 = 0; 150 int cat = -1; 151 int nest; 152 static const char parse_error[] = "Parse error"; 153 int i; 154 155 *lino = 0; 156 for (i = 0; i < sizeof(pci_ids) / sizeof(char *); i++) { 157 line = (byte *) pci_ids[i]; 158 (*lino)++; 159 p = line; 160 while (*p) 161 p++; 162 if (p > line && (p[-1] == ' ' || p[-1] == '\t')) 163 *--p = 0; 164 165 p = line; 166 while (id_white_p(*p)) 167 p++; 168 if (!*p || *p == '#') 169 continue; 170 171 p = line; 172 while (*p == '\t') 173 p++; 174 nest = p - line; 175 176 if (!nest) { /* Top-level entries */ 177 if (p[0] == 'C' && p[1] == ' ') { /* Class block */ 178 if ((id1 = id_hex(p + 2, 2)) < 0 179 || !id_white_p(p[4])) 180 return parse_error; 181 cat = ID_CLASS; 182 p += 5; 183 } else if (p[0] == 'S' && p[1] == ' ') { /* Generic subsystem block */ 184 if ((id1 = id_hex(p + 2, 4)) < 0 || p[6]) 185 return parse_error; 186 if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0)) 187 return "Vendor does not exist"; 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; 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; 200 } 201 id2 = id3 = id4 = 0; 202 } else if (cat == ID_UNKNOWN) /* Nested entries in RFU blocks are skipped */ 203 continue; 204 else if (nest == 1) /* Nesting level 1 */ 205 switch (cat) { 206 case ID_VENDOR: 207 case ID_DEVICE: 208 case ID_SUBSYSTEM: 209 if ((id2 = id_hex(p, 4)) < 0 210 || !id_white_p(p[4])) 211 return parse_error; 212 p += 5; 213 cat = ID_DEVICE; 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; 220 p += 5; 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; 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: 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])) 243 return parse_error; 244 p += 10; 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; 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)) 262 p++; 263 if (!*p) 264 return parse_error; 265 if (id_insert(a, cat, id1, id2, id3, id4, p)) 266 return "Duplicate entry"; 267 } 341 268 return NULL; 342 } 343 else 344 synth = 1; 345 346 switch (flags) 347 { 348 case PCI_LOOKUP_VENDOR: 349 iv = va_arg(args, int); 350 if (num) 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; 354 else 355 res = snprintf(buf, size, "Unknown vendor %04x", iv); 356 break; 357 case PCI_LOOKUP_DEVICE: 358 iv = va_arg(args, int); 359 id = va_arg(args, int); 360 if (num) 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); 366 else 367 return NULL; 368 break; 369 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE: 370 iv = va_arg(args, int); 371 id = va_arg(args, int); 372 if (num) 373 res = snprintf(buf, size, "%04x:%04x", iv, id); 374 else 375 { 376 v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0); 377 d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); 378 if (v && d) 379 res = snprintf(buf, size, "%s %s", v->name, d->name); 380 else if (!synth) 381 return NULL; 382 else if (!v) 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 } 387 break; 388 case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR: 389 isv = va_arg(args, int); 390 if (num) 391 res = snprintf(buf, size, "%04x", isv); 392 else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) 393 return (char *) v->name; 394 else if (synth) 395 res = snprintf(buf, size, "Unknown vendor %04x", 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 = snprintf(buf, size, "Unknown device %04x", isd); 410 else 411 return NULL; 412 break; 413 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: 414 iv = va_arg(args, int); 415 id = va_arg(args, int); 416 isv = va_arg(args, int); 417 isd = va_arg(args, int); 418 if (num) 419 res = snprintf(buf, size, "%04x:%04x", isv, isd); 420 else 421 { 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) 425 res = snprintf(buf, size, "%s %s", v->name, d->name); 426 else if (!synth) 427 return NULL; 428 else if (!v) 429 res = snprintf(buf, size, "Unknown device %04x:%04x", isv, isd); 430 else /* !d */ 431 res = snprintf(buf, size, "%s Unknown device %04x", v->name, isd); 432 } 433 break; 434 case PCI_LOOKUP_CLASS: 435 icls = va_arg(args, int); 436 if (num) 437 res = snprintf(buf, size, "%04x", icls); 438 else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) 439 return (char *) cls->name; 440 else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) 441 res = snprintf(buf, size, "%s [%04x]", cls->name, icls); 442 else if (synth) 443 res = snprintf(buf, size, "Class %04x", icls); 444 else 445 return NULL; 446 break; 447 case PCI_LOOKUP_PROGIF: 448 icls = va_arg(args, int); 449 ipif = va_arg(args, int); 450 if (num) 451 res = snprintf(buf, size, "%02x", ipif); 452 else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) 453 return (char *) pif->name; 454 else if (icls == 0x0101 && !(ipif & 0x70)) 455 { 456 /* IDE controllers have complex prog-if semantics */ 457 res = snprintf(buf, size, "%s%s%s%s%s", 458 (ipif & 0x80) ? "Master " : "", 459 (ipif & 0x08) ? "SecP " : "", 460 (ipif & 0x04) ? "SecO " : "", 461 (ipif & 0x02) ? "PriP " : "", 462 (ipif & 0x01) ? "PriO " : ""); 463 if (res > 0 && res < size) 464 buf[--res] = 0; 465 } 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) 475 return "<pci_lookup_name: buffer too small>"; 476 else 477 return buf; 478 } 269 } 270 271 int pci_load_name_list(struct pci_access *a) 272 { 273 int lino; 274 const char *err; 275 276 pci_free_name_list(a); 277 a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE); 278 bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE); 279 err = id_parse_list(a, &lino); 280 if (err) 281 a->error("%s at %s, element %d\n", err, "pci_ids.h", lino); 282 return 1; 283 } 284 285 void pci_free_name_list(struct pci_access *a) 286 { 287 pci_mfree(a->id_hash); 288 a->id_hash = NULL; 289 while (a->current_id_bucket) { 290 struct id_bucket *buck = a->current_id_bucket; 291 a->current_id_bucket = buck->next; 292 pci_mfree(buck); 293 } 294 } 295 296 static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, 297 int id, int isv, int isd) 298 { 299 struct id_entry *d = NULL; 300 if (iv > 0 && id > 0) /* Per-device lookup */ 301 d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd); 302 if (!d) /* Generic lookup */ 303 d = id_lookup(a, ID_GEN_SUBSYSTEM, isv, isd, 0, 0); 304 if (!d && iv == isv && id == isd) /* Check for subsystem == device */ 305 d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); 306 return d; 307 } 308 309 char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, 310 ...) 311 { 312 va_list args; 313 int num, res, synth; 314 struct id_entry *v, *d, *cls, *pif; 315 int iv, id, isv, isd, icls, ipif; 316 317 va_start(args, flags); 318 319 num = 0; 320 if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids) { 321 flags &= ~PCI_LOOKUP_NUMERIC; 322 num = 1; 323 } else if (!a->id_hash) { 324 if (!pci_load_name_list(a)) 325 num = a->numeric_ids = 1; 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 } 442 break; 443 case PCI_LOOKUP_CLASS: 444 icls = va_arg(args, int); 445 if (num) 446 res = snprintf(buf, size, "%04x", icls); 447 else if (cls = 448 id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 449 0, 0)) 450 return (char *) cls->name; 451 else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) 452 res = 453 snprintf(buf, size, "%s [%04x]", cls->name, 454 icls); 455 else if (synth) 456 res = snprintf(buf, size, "Class %04x", icls); 457 else 458 return NULL; 459 break; 460 case PCI_LOOKUP_PROGIF: 461 icls = va_arg(args, int); 462 ipif = va_arg(args, int); 463 if (num) 464 res = snprintf(buf, size, "%02x", ipif); 465 else if (pif = 466 id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, 467 ipif, 0)) 468 return (char *) pif->name; 469 else if (icls == 0x0101 && !(ipif & 0x70)) { 470 /* IDE controllers have complex prog-if semantics */ 471 res = snprintf(buf, size, "%s%s%s%s%s", 472 (ipif & 0x80) ? "Master " : "", 473 (ipif & 0x08) ? "SecP " : "", 474 (ipif & 0x04) ? "SecO " : "", 475 (ipif & 0x02) ? "PriP " : "", 476 (ipif & 0x01) ? "PriO " : ""); 477 if (res > 0 && res < size) 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>"; 486 } 487 if (res < 0 || res >= size) 488 return "<pci_lookup_name: buffer too small>"; 489 else 490 return buf; 491 }
Note:
See TracChangeset
for help on using the changeset viewer.