Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/pci/direct.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* direct.c - Low-level direct PCI config space access
4
*/
5
6
#include <linux/pci.h>
7
#include <linux/init.h>
8
#include <linux/dmi.h>
9
#include <asm/pci_x86.h>
10
11
/*
12
* Functions for accessing PCI base (first 256 bytes) and extended
13
* (4096 bytes per PCI function) configuration space with type 1
14
* accesses.
15
*/
16
17
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
18
(0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
19
| (devfn << 8) | (reg & 0xFC))
20
21
static int pci_conf1_read(unsigned int seg, unsigned int bus,
22
unsigned int devfn, int reg, int len, u32 *value)
23
{
24
unsigned long flags;
25
26
if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) {
27
*value = -1;
28
return -EINVAL;
29
}
30
31
raw_spin_lock_irqsave(&pci_config_lock, flags);
32
33
outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
34
35
switch (len) {
36
case 1:
37
*value = inb(0xCFC + (reg & 3));
38
break;
39
case 2:
40
*value = inw(0xCFC + (reg & 2));
41
break;
42
case 4:
43
*value = inl(0xCFC);
44
break;
45
}
46
47
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
48
49
return 0;
50
}
51
52
static int pci_conf1_write(unsigned int seg, unsigned int bus,
53
unsigned int devfn, int reg, int len, u32 value)
54
{
55
unsigned long flags;
56
57
if (seg || (bus > 255) || (devfn > 255) || (reg > 4095))
58
return -EINVAL;
59
60
raw_spin_lock_irqsave(&pci_config_lock, flags);
61
62
outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
63
64
switch (len) {
65
case 1:
66
outb((u8)value, 0xCFC + (reg & 3));
67
break;
68
case 2:
69
outw((u16)value, 0xCFC + (reg & 2));
70
break;
71
case 4:
72
outl((u32)value, 0xCFC);
73
break;
74
}
75
76
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
77
78
return 0;
79
}
80
81
#undef PCI_CONF1_ADDRESS
82
83
const struct pci_raw_ops pci_direct_conf1 = {
84
.read = pci_conf1_read,
85
.write = pci_conf1_write,
86
};
87
88
89
/*
90
* Functions for accessing PCI configuration space with type 2 accesses
91
*/
92
93
#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg)
94
95
static int pci_conf2_read(unsigned int seg, unsigned int bus,
96
unsigned int devfn, int reg, int len, u32 *value)
97
{
98
unsigned long flags;
99
int dev, fn;
100
101
WARN_ON(seg);
102
if ((bus > 255) || (devfn > 255) || (reg > 255)) {
103
*value = -1;
104
return -EINVAL;
105
}
106
107
dev = PCI_SLOT(devfn);
108
fn = PCI_FUNC(devfn);
109
110
if (dev & 0x10)
111
return PCIBIOS_DEVICE_NOT_FOUND;
112
113
raw_spin_lock_irqsave(&pci_config_lock, flags);
114
115
outb((u8)(0xF0 | (fn << 1)), 0xCF8);
116
outb((u8)bus, 0xCFA);
117
118
switch (len) {
119
case 1:
120
*value = inb(PCI_CONF2_ADDRESS(dev, reg));
121
break;
122
case 2:
123
*value = inw(PCI_CONF2_ADDRESS(dev, reg));
124
break;
125
case 4:
126
*value = inl(PCI_CONF2_ADDRESS(dev, reg));
127
break;
128
}
129
130
outb(0, 0xCF8);
131
132
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
133
134
return 0;
135
}
136
137
static int pci_conf2_write(unsigned int seg, unsigned int bus,
138
unsigned int devfn, int reg, int len, u32 value)
139
{
140
unsigned long flags;
141
int dev, fn;
142
143
WARN_ON(seg);
144
if ((bus > 255) || (devfn > 255) || (reg > 255))
145
return -EINVAL;
146
147
dev = PCI_SLOT(devfn);
148
fn = PCI_FUNC(devfn);
149
150
if (dev & 0x10)
151
return PCIBIOS_DEVICE_NOT_FOUND;
152
153
raw_spin_lock_irqsave(&pci_config_lock, flags);
154
155
outb((u8)(0xF0 | (fn << 1)), 0xCF8);
156
outb((u8)bus, 0xCFA);
157
158
switch (len) {
159
case 1:
160
outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
161
break;
162
case 2:
163
outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
164
break;
165
case 4:
166
outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
167
break;
168
}
169
170
outb(0, 0xCF8);
171
172
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
173
174
return 0;
175
}
176
177
#undef PCI_CONF2_ADDRESS
178
179
static const struct pci_raw_ops pci_direct_conf2 = {
180
.read = pci_conf2_read,
181
.write = pci_conf2_write,
182
};
183
184
185
/*
186
* Before we decide to use direct hardware access mechanisms, we try to do some
187
* trivial checks to ensure it at least _seems_ to be working -- we just test
188
* whether bus 00 contains a host bridge (this is similar to checking
189
* techniques used in XFree86, but ours should be more reliable since we
190
* attempt to make use of direct access hints provided by the PCI BIOS).
191
*
192
* This should be close to trivial, but it isn't, because there are buggy
193
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
194
*/
195
static int __init pci_sanity_check(const struct pci_raw_ops *o)
196
{
197
u32 x = 0;
198
int devfn;
199
200
if (pci_probe & PCI_NO_CHECKS)
201
return 1;
202
/* Assume Type 1 works for newer systems.
203
This handles machines that don't have anything on PCI Bus 0. */
204
if (dmi_get_bios_year() >= 2001)
205
return 1;
206
207
for (devfn = 0; devfn < 0x100; devfn++) {
208
if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
209
continue;
210
if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
211
return 1;
212
213
if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
214
continue;
215
if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
216
return 1;
217
}
218
219
DBG(KERN_WARNING "PCI: Sanity check failed\n");
220
return 0;
221
}
222
223
static int __init pci_check_type1(void)
224
{
225
unsigned long flags;
226
unsigned int tmp;
227
int works = 0;
228
229
local_irq_save(flags);
230
231
outb(0x01, 0xCFB);
232
tmp = inl(0xCF8);
233
outl(0x80000000, 0xCF8);
234
if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
235
works = 1;
236
}
237
outl(tmp, 0xCF8);
238
local_irq_restore(flags);
239
240
return works;
241
}
242
243
static int __init pci_check_type2(void)
244
{
245
unsigned long flags;
246
int works = 0;
247
248
local_irq_save(flags);
249
250
outb(0x00, 0xCFB);
251
outb(0x00, 0xCF8);
252
outb(0x00, 0xCFA);
253
if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
254
pci_sanity_check(&pci_direct_conf2)) {
255
works = 1;
256
}
257
258
local_irq_restore(flags);
259
260
return works;
261
}
262
263
void __init pci_direct_init(int type)
264
{
265
if (type == 0)
266
return;
267
printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
268
type);
269
if (type == 1) {
270
raw_pci_ops = &pci_direct_conf1;
271
if (raw_pci_ext_ops)
272
return;
273
if (!(pci_probe & PCI_HAS_IO_ECS))
274
return;
275
printk(KERN_INFO "PCI: Using configuration type 1 "
276
"for extended access\n");
277
raw_pci_ext_ops = &pci_direct_conf1;
278
return;
279
}
280
raw_pci_ops = &pci_direct_conf2;
281
}
282
283
int __init pci_direct_probe(void)
284
{
285
if ((pci_probe & PCI_PROBE_CONF1) == 0)
286
goto type2;
287
if (!request_region(0xCF8, 8, "PCI conf1"))
288
goto type2;
289
290
if (pci_check_type1()) {
291
raw_pci_ops = &pci_direct_conf1;
292
port_cf9_safe = true;
293
return 1;
294
}
295
release_region(0xCF8, 8);
296
297
type2:
298
if ((pci_probe & PCI_PROBE_CONF2) == 0)
299
return 0;
300
if (!request_region(0xCF8, 4, "PCI conf2"))
301
return 0;
302
if (!request_region(0xC000, 0x1000, "PCI conf2"))
303
goto fail2;
304
305
if (pci_check_type2()) {
306
raw_pci_ops = &pci_direct_conf2;
307
port_cf9_safe = true;
308
return 2;
309
}
310
311
release_region(0xC000, 0x1000);
312
fail2:
313
release_region(0xCF8, 4);
314
return 0;
315
}
316
317