Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/pci/early.c
10817 views
1
#include <linux/kernel.h>
2
#include <linux/pci.h>
3
#include <asm/pci-direct.h>
4
#include <asm/io.h>
5
#include <asm/pci_x86.h>
6
7
/* Direct PCI access. This is used for PCI accesses in early boot before
8
the PCI subsystem works. */
9
10
u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
11
{
12
u32 v;
13
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
14
v = inl(0xcfc);
15
return v;
16
}
17
18
u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
19
{
20
u8 v;
21
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
22
v = inb(0xcfc + (offset&3));
23
return v;
24
}
25
26
u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
27
{
28
u16 v;
29
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
30
v = inw(0xcfc + (offset&2));
31
return v;
32
}
33
34
void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
35
u32 val)
36
{
37
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
38
outl(val, 0xcfc);
39
}
40
41
void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
42
{
43
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
44
outb(val, 0xcfc + (offset&3));
45
}
46
47
void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val)
48
{
49
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
50
outw(val, 0xcfc + (offset&2));
51
}
52
53
int early_pci_allowed(void)
54
{
55
return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
56
PCI_PROBE_CONF1;
57
}
58
59
void early_dump_pci_device(u8 bus, u8 slot, u8 func)
60
{
61
int i;
62
int j;
63
u32 val;
64
65
printk(KERN_INFO "pci 0000:%02x:%02x.%d config space:",
66
bus, slot, func);
67
68
for (i = 0; i < 256; i += 4) {
69
if (!(i & 0x0f))
70
printk("\n %02x:",i);
71
72
val = read_pci_config(bus, slot, func, i);
73
for (j = 0; j < 4; j++) {
74
printk(" %02x", val & 0xff);
75
val >>= 8;
76
}
77
}
78
printk("\n");
79
}
80
81
void early_dump_pci_devices(void)
82
{
83
unsigned bus, slot, func;
84
85
if (!early_pci_allowed())
86
return;
87
88
for (bus = 0; bus < 256; bus++) {
89
for (slot = 0; slot < 32; slot++) {
90
for (func = 0; func < 8; func++) {
91
u32 class;
92
u8 type;
93
94
class = read_pci_config(bus, slot, func,
95
PCI_CLASS_REVISION);
96
if (class == 0xffffffff)
97
continue;
98
99
early_dump_pci_device(bus, slot, func);
100
101
if (func == 0) {
102
type = read_pci_config_byte(bus, slot,
103
func,
104
PCI_HEADER_TYPE);
105
if (!(type & 0x80))
106
break;
107
}
108
}
109
}
110
}
111
}
112
113