Annotation of embedaddon/pciutils/lib/caps.c, revision 1.1.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>