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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#ifndef __PCI_H
#define __PCI_H
#include "types.h" // u32
static inline u8 pci_bdf_to_bus(u16 bdf) {
return bdf >> 8;
}
static inline u8 pci_bdf_to_devfn(u16 bdf) {
return bdf & 0xff;
}
static inline u16 pci_bdf_to_busdev(u16 bdf) {
return bdf & ~0x07;
}
static inline u8 pci_bdf_to_dev(u16 bdf) {
return (bdf >> 3) & 0x1f;
}
static inline u8 pci_bdf_to_fn(u16 bdf) {
return bdf & 0x07;
}
static inline u16 pci_to_bdf(int bus, int dev, int fn) {
return (bus<<8) | (dev<<3) | fn;
}
static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
return (bus << 8) | devfn;
}
void pci_config_writel(u16 bdf, u32 addr, u32 val);
void pci_config_writew(u16 bdf, u32 addr, u16 val);
void pci_config_writeb(u16 bdf, u32 addr, u8 val);
u32 pci_config_readl(u16 bdf, u32 addr);
u16 pci_config_readw(u16 bdf, u32 addr);
u8 pci_config_readb(u16 bdf, u32 addr);
void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
struct pci_device *pci_find_device(u16 vendid, u16 devid);
struct pci_device *pci_find_class(u16 classid);
struct pci_device {
u16 bdf;
u8 rootbus;
struct pci_device *next;
struct pci_device *parent;
// Configuration space device information
u16 vendor, device;
u16 class;
u8 prog_if, revision;
u8 header_type;
u8 secondary_bus;
// Local information on device.
int have_driver;
};
extern struct pci_device *PCIDevices;
extern int MaxPCIBus;
void pci_probe(void);
static inline u32 pci_classprog(struct pci_device *pci) {
return (pci->class << 8) | pci->prog_if;
}
#define foreachpci(PCI) \
for (PCI=PCIDevices; PCI; PCI=PCI->next)
int pci_next(int bdf, int *pmax);
#define foreachbdf(BDF, MAX) \
for (MAX=0x0100, BDF=pci_next(0, &MAX) \
; BDF >= 0 \
; BDF=pci_next(BDF+1, &MAX))
#define foreachbdf_in_bus(BDF, MAX, BUS) \
for (MAX = pci_bus_devfn_to_bdf(BUS, 0) + 0x0100, \
BDF = pci_next(pci_bus_devfn_to_bdf(BUS, 0), &MAX) \
; BDF >= 0 && BDF < pci_bus_devfn_to_bdf(BUS, 0) + 0x0100 \
; MAX = pci_bus_devfn_to_bdf(BUS, 0) + 0x0100, \
BDF = pci_next(BDF + 1, &MAX))
#define PCI_ANY_ID (~0)
struct pci_device_id {
u32 vendid;
u32 devid;
u32 class;
u32 class_mask;
void (*func)(struct pci_device *pci, void *arg);
};
#define PCI_DEVICE(vendor_id, device_id, init_func) \
{ \
.vendid = (vendor_id), \
.devid = (device_id), \
.class = PCI_ANY_ID, \
.class_mask = 0, \
.func = (init_func) \
}
#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func) \
{ \
.vendid = (vendor_id), \
.devid = (device_id), \
.class = (class_code), \
.class_mask = ~0, \
.func = (init_func) \
}
#define PCI_DEVICE_END \
{ \
.vendid = 0, \
}
int pci_init_device(const struct pci_device_id *ids
, struct pci_device *pci, void *arg);
struct pci_device *pci_find_init_device(const struct pci_device_id *ids
, void *arg);
void pci_reboot(void);
// helper functions to access pci mmio bars from real mode
u32 pci_readl(u32 addr);
void pci_writel(u32 addr, u32 val);
// pirtable.c
void create_pirtable(void);
/****************************************************************
* PIR table
****************************************************************/
extern u16 PirOffset;
struct link_info {
u8 link;
u16 bitmap;
} PACKED;
struct pir_slot {
u8 bus;
u8 dev;
struct link_info links[4];
u8 slot_nr;
u8 reserved;
} PACKED;
struct pir_header {
u32 signature;
u16 version;
u16 size;
u8 router_bus;
u8 router_devfunc;
u16 exclusive_irqs;
u32 compatible_devid;
u32 miniport_data;
u8 reserved[11];
u8 checksum;
struct pir_slot slots[0];
} PACKED;
#define PIR_SIGNATURE 0x52495024 // $PIR
#endif
|