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
10u32 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
18u8 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
26u16 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
34void 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
41void 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
47void 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
53int early_pci_allowed(void)
54{
55	return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
56			PCI_PROBE_CONF1;
57}
58
59void 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
81void 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