Changeset 20a9b85 in mainline for pci/libpci/names.c


Ignore:
Timestamp:
2006-05-09T10:55:02Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
46ec2c06
Parents:
4a7c273
Message:

Change libpci coding style.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pci/libpci/names.c

    r4a7c273 r20a9b85  
    1919
    2020struct id_entry {
    21   struct id_entry *next;
    22   u32 id12, id34;
    23   byte cat;
    24   byte name[1];
     21        struct id_entry *next;
     22        u32 id12, id34;
     23        byte cat;
     24        byte name[1];
    2525};
    2626
    2727enum id_entry_type {
    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
     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
    3636};
    3737
    3838struct id_bucket {
    39   struct id_bucket *next;
    40   unsigned int full;
     39        struct id_bucket *next;
     40        unsigned int full;
    4141};
    4242
     
    4949#else
    5050union id_align {
    51   struct id_bucket *next;
    52   unsigned int full;
     51        struct id_bucket *next;
     52        unsigned int full;
    5353};
    5454#define BUCKET_ALIGNMENT sizeof(union id_align)
     
    5858static void *id_alloc(struct pci_access *a, unsigned int size)
    5959{
    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;
    7271}
    7372
    7473static inline u32 id_pair(unsigned int x, unsigned int y)
    7574{
    76   return ((x << 16) | y);
     75        return ((x << 16) | y);
    7776}
    7877
    7978static inline unsigned int id_hash(int cat, u32 id12, u32 id34)
    8079{
    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
     86static 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
     99static 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
     122static 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;
    138138}
    139139
    140140static inline int id_white_p(int c)
    141141{
    142   return (c == ' ') || (c == '\t');
     142        return (c == ' ') || (c == '\t');
    143143}
    144144
    145145static const char *id_parse_list(struct pci_access *a, int *lino)
    146146{
    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        }
    341268        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
     271int 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
     285void 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
     296static 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
     309char *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.