Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/drivers/pci/pci.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * pci.c
3
 *
4
 * Architecture-independent PCI access functions.
5
 */
6
7
#include <xen/init.h>
8
#include <xen/pci.h>
9
#include <xen/pci_regs.h>
10
11
int pci_find_cap_offset(u16 seg, u8 bus, u8 dev, u8 func, u8 cap)
12
349
{
13
349
    u8 id;
14
349
    int max_cap = 48;
15
349
    u8 pos = PCI_CAPABILITY_LIST;
16
349
    u16 status;
17
349
18
349
    status = pci_conf_read16(seg, bus, dev, func, PCI_STATUS);
19
349
    if ( (status & PCI_STATUS_CAP_LIST) == 0 )
20
96
        return 0;
21
349
22
650
    while ( max_cap-- )
23
650
    {
24
650
        pos = pci_conf_read8(seg, bus, dev, func, pos);
25
650
        if ( pos < 0x40 )
26
110
            break;
27
650
28
540
        pos &= ~3;
29
540
        id = pci_conf_read8(seg, bus, dev, func, pos + PCI_CAP_LIST_ID);
30
540
31
540
        if ( id == 0xff )
32
0
            break;
33
540
        else if ( id == cap )
34
143
            return pos;
35
540
36
397
        pos += PCI_CAP_LIST_NEXT;
37
397
    }
38
253
39
110
    return 0;
40
253
}
41
42
int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, u8 pos, int cap)
43
0
{
44
0
    u8 id;
45
0
    int ttl = 48;
46
0
47
0
    while ( ttl-- )
48
0
    {
49
0
        pos = pci_conf_read8(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
50
0
        if ( pos < 0x40 )
51
0
            break;
52
0
53
0
        pos &= ~3;
54
0
        id = pci_conf_read8(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
55
0
                            pos + PCI_CAP_LIST_ID);
56
0
57
0
        if ( id == 0xff )
58
0
            break;
59
0
        if ( id == cap )
60
0
            return pos;
61
0
62
0
        pos += PCI_CAP_LIST_NEXT;
63
0
    }
64
0
    return 0;
65
0
}
66
67
/**
68
 * pci_find_ext_capability - Find an extended capability
69
 * @seg/@bus/@devfn: PCI device to query
70
 * @cap: capability code
71
 *
72
 * Returns the address of the requested extended capability structure
73
 * within the device's PCI configuration space or 0 if the device does
74
 * not support it.
75
 */
76
int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
77
0
{
78
0
    return pci_find_next_ext_capability(seg, bus, devfn, 0, cap);
79
0
}
80
81
/**
82
 * pci_find_next_ext_capability - Find another extended capability
83
 * @seg/@bus/@devfn: PCI device to query
84
 * @pos: starting position
85
 * @cap: capability code
86
 *
87
 * Returns the address of the requested extended capability structure
88
 * within the device's PCI configuration space or 0 if the device does
89
 * not support it.
90
 */
91
int pci_find_next_ext_capability(int seg, int bus, int devfn, int start, int cap)
92
0
{
93
0
    u32 header;
94
0
    int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
95
0
    int pos = max(start, 0x100);
96
0
97
0
    header = pci_conf_read32(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
98
0
99
0
    /*
100
0
     * If we have no capabilities, this is indicated by cap ID,
101
0
     * cap version and next pointer all being 0.
102
0
     */
103
0
    if ( (header == 0) || (header == -1) )
104
0
        return 0;
105
0
    ASSERT(start != pos || PCI_EXT_CAP_ID(header) == cap);
106
0
107
0
    while ( ttl-- > 0 ) {
108
0
        if ( PCI_EXT_CAP_ID(header) == cap && pos != start )
109
0
            return pos;
110
0
        pos = PCI_EXT_CAP_NEXT(header);
111
0
        if ( pos < 0x100 )
112
0
            break;
113
0
        header = pci_conf_read32(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
114
0
    }
115
0
    return 0;
116
0
}
117
118
const char *__init parse_pci(const char *s, unsigned int *seg_p,
119
                             unsigned int *bus_p, unsigned int *dev_p,
120
                             unsigned int *func_p)
121
0
{
122
0
    bool def_seg;
123
0
124
0
    return parse_pci_seg(s, seg_p, bus_p, dev_p, func_p, &def_seg);
125
0
}
126
127
const char *__init parse_pci_seg(const char *s, unsigned int *seg_p,
128
                                 unsigned int *bus_p, unsigned int *dev_p,
129
                                 unsigned int *func_p, bool *def_seg)
130
0
{
131
0
    unsigned long seg = simple_strtoul(s, &s, 16), bus, dev, func;
132
0
133
0
    if ( *s != ':' )
134
0
        return NULL;
135
0
    bus = simple_strtoul(s + 1, &s, 16);
136
0
    *def_seg = false;
137
0
    if ( *s == ':' )
138
0
        dev = simple_strtoul(s + 1, &s, 16);
139
0
    else
140
0
    {
141
0
        dev = bus;
142
0
        bus = seg;
143
0
        seg = 0;
144
0
        *def_seg = true;
145
0
    }
146
0
    if ( func_p )
147
0
    {
148
0
        if ( *s != '.' )
149
0
            return NULL;
150
0
        func = simple_strtoul(s + 1, &s, 0);
151
0
    }
152
0
    else
153
0
        func = 0;
154
0
    if ( seg != (seg_p ? (u16)seg : 0) ||
155
0
         bus != PCI_BUS(PCI_BDF2(bus, 0)) ||
156
0
         dev != PCI_SLOT(PCI_DEVFN(dev, 0)) ||
157
0
         func != PCI_FUNC(PCI_DEVFN(0, func)) )
158
0
        return NULL;
159
0
160
0
    if ( seg_p )
161
0
        *seg_p = seg;
162
0
    *bus_p = bus;
163
0
    *dev_p = dev;
164
0
    if ( func_p )
165
0
        *func_p = func;
166
0
167
0
    return s;
168
0
}