Annotation of embedaddon/pciutils/lib/caps.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     The PCI Library -- Capabilities
        !             3:  *
        !             4:  *     Copyright (c) 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: 
        !            13: static void
        !            14: pci_add_cap(struct pci_dev *d, unsigned int addr, unsigned int id, unsigned int type)
        !            15: {
        !            16:   struct pci_cap *cap = pci_malloc(d->access, sizeof(*cap));
        !            17: 
        !            18:   cap->next = d->first_cap;
        !            19:   d->first_cap = cap;
        !            20:   cap->addr = addr;
        !            21:   cap->id = id;
        !            22:   cap->type = type;
        !            23:   d->access->debug("%04x:%02x:%02x.%d: Found capability %04x of type %d at %04x\n",
        !            24:     d->domain, d->bus, d->dev, d->func, id, type, addr);
        !            25: }
        !            26: 
        !            27: static void
        !            28: pci_scan_trad_caps(struct pci_dev *d)
        !            29: {
        !            30:   word status = pci_read_word(d, PCI_STATUS);
        !            31:   byte been_there[256];
        !            32:   int where;
        !            33: 
        !            34:   if (!(status & PCI_STATUS_CAP_LIST))
        !            35:     return;
        !            36: 
        !            37:   memset(been_there, 0, 256);
        !            38:   where = pci_read_byte(d, PCI_CAPABILITY_LIST) & ~3;
        !            39:   while (where)
        !            40:     {
        !            41:       byte id = pci_read_byte(d, where + PCI_CAP_LIST_ID);
        !            42:       byte next = pci_read_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
        !            43:       if (been_there[where]++)
        !            44:        break;
        !            45:       if (id == 0xff)
        !            46:        break;
        !            47:       pci_add_cap(d, where, id, PCI_CAP_NORMAL);
        !            48:       where = next;
        !            49:     }
        !            50: }
        !            51: 
        !            52: static void
        !            53: pci_scan_ext_caps(struct pci_dev *d)
        !            54: {
        !            55:   byte been_there[0x1000];
        !            56:   int where = 0x100;
        !            57: 
        !            58:   if (!pci_find_cap(d, PCI_CAP_ID_EXP, PCI_CAP_NORMAL))
        !            59:     return;
        !            60: 
        !            61:   memset(been_there, 0, 0x1000);
        !            62:   do
        !            63:     {
        !            64:       u32 header;
        !            65:       int id;
        !            66: 
        !            67:       header = pci_read_long(d, where);
        !            68:       if (!header || header == 0xffffffff)
        !            69:        break;
        !            70:       id = header & 0xffff;
        !            71:       if (been_there[where]++)
        !            72:        break;
        !            73:       pci_add_cap(d, where, id, PCI_CAP_EXTENDED);
        !            74:       where = (header >> 20) & ~3;
        !            75:     }
        !            76:   while (where);
        !            77: }
        !            78: 
        !            79: unsigned int
        !            80: pci_scan_caps(struct pci_dev *d, unsigned int want_fields)
        !            81: {
        !            82:   if ((want_fields & PCI_FILL_EXT_CAPS) && !(d->known_fields & PCI_FILL_CAPS))
        !            83:     want_fields |= PCI_FILL_CAPS;
        !            84: 
        !            85:   if (want_fields & PCI_FILL_CAPS)
        !            86:     pci_scan_trad_caps(d);
        !            87:   if (want_fields & PCI_FILL_EXT_CAPS)
        !            88:     pci_scan_ext_caps(d);
        !            89:   return want_fields;
        !            90: }
        !            91: 
        !            92: void
        !            93: pci_free_caps(struct pci_dev *d)
        !            94: {
        !            95:   struct pci_cap *cap;
        !            96: 
        !            97:   while (cap = d->first_cap)
        !            98:     {
        !            99:       d->first_cap = cap->next;
        !           100:       pci_mfree(cap);
        !           101:     }
        !           102: }
        !           103: 
        !           104: struct pci_cap *
        !           105: pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type)
        !           106: {
        !           107:   struct pci_cap *c;
        !           108: 
        !           109:   pci_fill_info_v31(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
        !           110:   for (c=d->first_cap; c; c=c->next)
        !           111:     if (c->type == type && c->id == id)
        !           112:       return c;
        !           113:   return NULL;
        !           114: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>