]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - lib/caps.c
2 * The PCI Library -- Capabilities
4 * Copyright (c) 2008 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
14 pci_add_cap(struct pci_dev
*d
, unsigned int addr
, unsigned int id
, unsigned int type
)
16 struct pci_cap
*cap
= pci_malloc(d
->access
, sizeof(*cap
));
19 d
->last_cap
->next
= cap
;
26 d
->access
->debug("%04x:%02x:%02x.%d: Found capability %04x of type %d at %04x\n",
27 d
->domain
, d
->bus
, d
->dev
, d
->func
, id
, type
, addr
);
31 pci_scan_trad_caps(struct pci_dev
*d
)
33 word status
= pci_read_word(d
, PCI_STATUS
);
37 if (!(status
& PCI_STATUS_CAP_LIST
))
40 memset(been_there
, 0, 256);
41 where
= pci_read_byte(d
, PCI_CAPABILITY_LIST
) & ~3;
44 byte id
= pci_read_byte(d
, where
+ PCI_CAP_LIST_ID
);
45 byte next
= pci_read_byte(d
, where
+ PCI_CAP_LIST_NEXT
) & ~3;
46 if (been_there
[where
]++)
50 pci_add_cap(d
, where
, id
, PCI_CAP_NORMAL
);
56 pci_scan_ext_caps(struct pci_dev
*d
)
58 byte been_there
[0x1000];
61 if (!pci_find_cap(d
, PCI_CAP_ID_EXP
, PCI_CAP_NORMAL
))
64 memset(been_there
, 0, 0x1000);
70 header
= pci_read_long(d
, where
);
71 if (!header
|| header
== 0xffffffff)
74 if (been_there
[where
]++)
76 pci_add_cap(d
, where
, id
, PCI_CAP_EXTENDED
);
77 where
= (header
>> 20) & ~3;
83 pci_scan_caps(struct pci_dev
*d
, unsigned int want_fields
)
85 if ((want_fields
& PCI_FILL_EXT_CAPS
) && !(d
->known_fields
& PCI_FILL_CAPS
))
86 want_fields
|= PCI_FILL_CAPS
;
88 if (want_fields
& PCI_FILL_CAPS
)
89 pci_scan_trad_caps(d
);
90 if (want_fields
& PCI_FILL_EXT_CAPS
)
96 pci_free_caps(struct pci_dev
*d
)
100 while (cap
= d
->first_cap
)
102 d
->first_cap
= cap
->next
;
108 pci_find_cap(struct pci_dev
*d
, unsigned int id
, unsigned int type
)
110 return pci_find_cap_nr(d
, id
, type
, NULL
);
114 * Finds a particular capability of a device
116 * To select one capability if there are more than one with the same id, you
117 * can provide a pointer to an unsigned int that contains the index which you
118 * want as cap_number. If you don't care and are fine with the first one you
119 * can supply NULL. The cap_number will be replaced by the acutal number
120 * of capablities with that id.
123 pci_find_cap_nr(struct pci_dev
*d
, unsigned int id
, unsigned int type
,
124 unsigned int *cap_number
)
127 struct pci_cap
*found
= NULL
;
128 unsigned int target
= (cap_number
? *cap_number
: 0);
129 unsigned int index
= 0;
131 pci_fill_info_v35(d
, ((type
== PCI_CAP_NORMAL
) ? PCI_FILL_CAPS
: PCI_FILL_EXT_CAPS
));
133 for (c
=d
->first_cap
; c
; c
=c
->next
)
135 if (c
->type
== type
&& c
->id
== id
)