-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpci.c
129 lines (106 loc) · 3.41 KB
/
pci.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* =====================================================================================
*
* Filename: pci.c
*
* Description:
*
* Version: 1.0
* Created: 14.12.2011 10:03:46
* Revision: none
* Compiler: gcc
*
* Author: Georg Wassen (gw) (),
* Company:
*
* =====================================================================================
*/
#include "cpu.h"
#include "sync.h"
#include "info.h"
#include "driver.h"
#define IFV if (VERBOSE > 0 || VERBOSE_PCI > 0)
#define IFVV if (VERBOSE > 1 || VERBOSE_PCI > 1)
#define CONFIG_ADR 0xCF8
#define CONFIG_DATA 0xCFC
mutex_t pci_mutex = MUTEX_INITIALIZER;
/*
* see: http://wiki.osdev.org/PCI
*/
uint16_t pci_config_read(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset)
{
uint32_t adr;
uint16_t value;
adr = 0x80000000ul | ((uint32_t)bus << 16) | ((uint32_t)slot << 11) | (func << 8) | (offset & 0xfc);
mutex_lock(&pci_mutex);
outportl(CONFIG_ADR, adr);
//udelay(100);
value = (uint16_t)((inportl(CONFIG_DATA) >> ((offset & 2)*8)) & 0xFFFF);
mutex_unlock(&pci_mutex);
return value;
}
static unsigned pcie_configured = 0;
uint32_t pcie_config_read(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset)
{
ptr_t adr;
uint32_t *p;
if (!pcie_configured) {
printf("ERROR: PCIE not (yet) configured (memory not mapped).\n");
halt();
}
adr = hw_info.pcie_cfg[0].base_adr
+ (((ptr_t)bus << 20) | ((ptr_t)slot << 15) | ((ptr_t)slot << 15) | ((ptr_t)func << 12) | (offset & 0xFFF));
p = (uint32_t*)adr;
return *p;
}
void pci_init()
{
unsigned bus, slot;
uint16_t vendor, device;
unsigned u;
IFV printf("pci_init()\n");
/*
* read PCI devices
*/
for (bus=0; bus<16; bus++) {
for (slot=0; slot<32; slot++) {
vendor = pci_config_read(bus, slot, 0, 0);
if (vendor != 0xFFFF) {
device = pci_config_read(bus, slot, 0, 2);
IFV printf("PCI: %2x:%2x [%4x:%4x]\n", bus, slot, vendor, device);
driver_check_pci(vendor, device, bus, slot);
}
}
}
/*
* map PCIe configuration space
*/
if (hw_info.pcie_cnt > 0) {
// as long as PCIE_CNT == 1, we don't need to search for the config space, as there is only one.
for (u=0; u<hw_info.pcie_cnt; u++) {
IFVV printf("PCIe[%u]: 0x%x bus %u-%u\n", u, hw_info.pcie_cfg[u].base_adr,
(unsigned)hw_info.pcie_cfg[u].bus_start, (unsigned)hw_info.pcie_cfg[u].bus_end);
// TODO: where to map this?
// -> QEMU does not have any PCIe regions...
}
//pcie_configured = 1;
/*
* read PCIe devices
*/
if (pcie_configured) {
for (bus=0; bus<2; bus++) {
for (slot=0; slot<64; slot++) {
//vendor = pci_config_read(bus, slot, 0, 0);
vendor = pcie_config_read(bus, slot, 0, 0);
if (vendor != 0xFFFF) {
device = pci_config_read(bus, slot, 0, 2);
IFV printf("PCIe: %2x:%2x [%4x:%4x]\n", bus, slot, vendor, device);
}
}
}
}
} else {
IFVV printf("PCIe: not found in ACPI tables.\n");
}
IFV printf("pci_init() finished.\n");
}