CS350 COS
COS
Loading...
Searching...
No Matches
pci.c
Go to the documentation of this file.
1
2#include <stdbool.h>
3#include <stdint.h>
4
5#include <sys/kassert.h>
6#include <sys/kdebug.h>
7#include <sys/pci.h>
8
9static void PCIScan();
10
11// Platform functions
15void PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func,
16 uint32_t reg, uint8_t data);
17void PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func,
18 uint32_t reg, uint16_t data);
19void PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func,
20 uint32_t reg, uint32_t data);
21
22// Supported Devices
23void AHCI_Init(uint32_t bus, uint32_t device, uint32_t func);
24void E1000_Init(uint32_t bus, uint32_t device, uint32_t func);
25
26void
28{
29 kprintf("PCI: Initializing ...\n");
30 PCIScan();
31 kprintf("PCI: Initialization Done!\n");
32}
33
36{
37 return PCICfgRead16(bus, device, func, PCI_OFFSET_DEVICEID);
38}
39
42{
43 return PCICfgRead16(bus, device, func, PCI_OFFSET_VENDORID);
44}
45
48{
49 return PCICfgRead8(bus, device, func, PCI_OFFSET_CLASS);
50}
51
54{
55 return PCICfgRead8(bus, device, func, PCI_OFFSET_SUBCLASS);
56}
57
60{
61 return PCICfgRead8(bus, device, func, PCI_OFFSET_HEADERTYPE);
62}
63
66{
67 return PCICfgRead8(dev->bus, dev->slot, dev->func, reg);
68}
69
72{
73 return PCICfgRead16(dev->bus, dev->slot, dev->func, reg);
74}
75
78{
79 return PCICfgRead32(dev->bus, dev->slot, dev->func, reg);
80}
81
82void
84{
85 return PCICfgWrite8(dev->bus, dev->slot, dev->func, reg, data);
86}
87
88void
90{
91 return PCICfgWrite16(dev->bus, dev->slot, dev->func, reg, data);
92}
93
94void
96{
97 return PCICfgWrite32(dev->bus, dev->slot, dev->func, reg, data);
98}
99
102{
104}
105
108{
110}
111
114{
115 return PCI_CfgRead8(dev, PCI_OFFSET_CLASS);
116}
117
120{
122}
123
126{
128}
129
130/*
131 * PCICheckFunction --
132 *
133 * Identify device type and initialize known devices.
134 */
135static void
137{
138 uint8_t baseClass, subClass;
139 uint16_t vendorId, deviceId;
140
141 baseClass = PCIGetBaseClass(bus, device, func);
142 subClass = PCIGetSubClass(bus, device, func);
143 vendorId = PCIGetVendorID(bus, device, func);
144 deviceId = PCIGetDeviceID(bus, device, func);
145
146 if (baseClass == PCI_CLASS_BRIDGE) {
147 if (subClass == PCI_SCLASS_BRIDGE_HOST) {
148 kprintf("PCI: (%d,%d,%d) Host Bridge (%04x:%04x)\n",
149 bus, device, func, vendorId, deviceId);
150 } else if (subClass == PCI_SCLASS_BRIDGE_ISA) {
151 kprintf("PCI: (%d,%d,%d) ISA Bridge (%04x:%04x)\n",
152 bus, device, func, vendorId, deviceId);
153 } else if (subClass == PCI_SCLASS_BRIDGE_PCI) {
154 kprintf("PCI: (%d,%d,%d) PCI-PCI Bridge (%04x:%04x)\n",
155 bus, device, func, vendorId, deviceId);
156 // Scan sub-bus
157 } else if (subClass == PCI_SCLASS_BRIDGE_MISC) {
158 kprintf("PCI: (%d,%d,%d) Other Bridge (%04x:%04x)\n",
159 bus, device, func, vendorId, deviceId);
160 }
161 } else if (baseClass == PCI_CLASS_STORAGE) {
162 if (subClass == PCI_SCLASS_STORAGE_SATA) {
163 kprintf("PCI: (%d,%d,%d) SATA Controller (%04x:%04x)\n",
164 bus, device, func, vendorId, deviceId);
165
166 AHCI_Init(bus, device, func);
167 } else if (subClass == PCI_SCLASS_STORAGE_IDE) {
168 kprintf("PCI: (%d,%d,%d) IDE Controller (%04x:%04x)\n",
169 bus, device, func, vendorId, deviceId);
170 }
171 } else if ((baseClass == PCI_CLASS_NETWORK) && (subClass == 0x00)) {
172 kprintf("PCI: (%d,%d,%d) Ethernet (%04x:%04x)\n",
173 bus, device, func, vendorId, deviceId);
174 E1000_Init(bus, device, func);
175 } else if ((baseClass == PCI_CLASS_GRAPHICS) && (subClass == 0x00)) {
176 kprintf("PCI: (%d,%d,%d) VGA (%04x:%04x)\n",
177 bus, device, func, vendorId, deviceId);
178 } else if ((baseClass == PCI_CLASS_BUS) && (subClass == PCI_SCLASS_BUS_SMBUS)) {
179 kprintf("PCI: (%d,%d,%d) SMBUS (%04x:%04x)\n",
180 bus, device, func, vendorId, deviceId);
181 } else {
182 kprintf("PCI: (%d,%d,%d) Unsupported (%04x:%04x %02x:%02x)\n",
183 bus, device, func, vendorId, deviceId, baseClass, subClass);
184 }
185}
186
187static void
189{
190 uint8_t headerType;
191 uint16_t vendorId;
192
193 vendorId = PCIGetVendorID(bus, device, 0);
194 if (vendorId == 0xFFFF)
195 return;
196
197 PCICheckFunction(bus, device, 0);
198
199 headerType = PCIGetHeaderType(bus, device, 0);
200 if ((headerType & 0x80) != 0) {
201 uint8_t func;
202 for (func = 0; func < 8; func++) {
203 if (PCIGetVendorID(bus, device, func) != 0xFFFF) {
204 PCICheckFunction(bus, device, func);
205 }
206 }
207 }
208}
209
210static void
212{
213 uint8_t device;
214
215 for (device = 0; device < 32; device++) {
216 PCIScanDevice(bus, device);
217 }
218}
219
220/*
221 * PCIScan --
222 *
223 * Scan all busses and devices.
224 */
225static void
227{
228 uint8_t headerType = PCIGetHeaderType(0, 0, 0);
229
230 if ((headerType & 0x80) == 0) {
231 PCIScanBus(0);
232 } else {
233 uint8_t busNo;
234
235 for (busNo = 0; busNo < 8; busNo++) {
236 if (PCIGetVendorID(0, 0, busNo) != 0xFFFF)
237 break;
238 PCIScanBus(busNo);
239 }
240 }
241}
242
243/*
244 * PCI_Configure --
245 *
246 * Configure a PCI device BAR registers.
247 */
248void
250{
251 int bar;
252
254
257
258 for (bar = 0; bar < PCI_MAX_BARS; bar++)
259 {
260 dev->bars[bar].base = 0;
261 dev->bars[bar].size = 0;
262 dev->bars[bar].type = PCIBAR_TYPE_NULL;
263 }
264
265 for (bar = 0; bar < PCI_MAX_BARS; bar++)
266 {
267 uint32_t barReg = PCI_OFFSET_BARFIRST + 4 * bar;
269 uint32_t origValue = PCI_CfgRead32(dev, barReg);
270
271 PCI_CfgWrite32(dev, barReg, 0xFFFFFFFF);
272 size = PCI_CfgRead32(dev, barReg);
273 if (size == 0)
274 continue;
275
276 PCI_CfgWrite32(dev, barReg, origValue);
277
278 if (origValue & 0x1)
279 {
280 dev->bars[bar].type = PCIBAR_TYPE_IO;
281 base = origValue & 0xFFFFFFFC;
282 size = size & 0xFFFFFFFC;
283 size = ~size + 1;
284 } else {
285 dev->bars[bar].type = PCIBAR_TYPE_MEM;
286 base = origValue & 0xFFFFFFF0;
287 size = size & 0xFFFFFFF0;
288 size = ~size + 1;
289 // XXX: Support 64-bit
290 ASSERT((origValue & 0x06) == 0x00);
291 }
292
293 dev->bars[bar].base = base;
294 dev->bars[bar].size = size;
295 }
296}
297
298static void
300{
301 uint8_t baseClass, subClass;
302 uint16_t vendorId, deviceId;
303
304 baseClass = PCIGetBaseClass(bus, device, func);
305 subClass = PCIGetSubClass(bus, device, func);
306 vendorId = PCIGetVendorID(bus, device, func);
307 deviceId = PCIGetDeviceID(bus, device, func);
308
309 if (baseClass == PCI_CLASS_BRIDGE) {
310 if (subClass == PCI_SCLASS_BRIDGE_HOST) {
311 kprintf("PCI: (%d,%d,%d) Host Bridge (%04x:%04x)\n",
312 bus, device, func, vendorId, deviceId);
313 } else if (subClass == PCI_SCLASS_BRIDGE_ISA) {
314 kprintf("PCI: (%d,%d,%d) ISA Bridge (%04x:%04x)\n",
315 bus, device, func, vendorId, deviceId);
316 } else if (subClass == PCI_SCLASS_BRIDGE_PCI) {
317 kprintf("PCI: (%d,%d,%d) PCI-PCI Bridge (%04x:%04x)\n",
318 bus, device, func, vendorId, deviceId);
319 // XXX: Scan sub-bus
320 } else if (subClass == PCI_SCLASS_BRIDGE_MISC) {
321 kprintf("PCI: (%d,%d,%d) Other Bridge (%04x:%04x)\n",
322 bus, device, func, vendorId, deviceId);
323 }
324 } else if (baseClass == PCI_CLASS_STORAGE) {
325 if (subClass == PCI_SCLASS_STORAGE_SATA) {
326 kprintf("PCI: (%d,%d,%d) SATA Controller (%04x:%04x)\n",
327 bus, device, func, vendorId, deviceId);
328 } else if (subClass == PCI_SCLASS_STORAGE_IDE) {
329 kprintf("PCI: (%d,%d,%d) IDE Controller (%04x:%04x)\n",
330 bus, device, func, vendorId, deviceId);
331 }
332 } else if ((baseClass == PCI_CLASS_NETWORK) && (subClass == 0x00)) {
333 kprintf("PCI: (%d,%d,%d) Ethernet (%04x:%04x)\n",
334 bus, device, func, vendorId, deviceId);
335 } else if ((baseClass == PCI_CLASS_GRAPHICS) && (subClass == 0x00)) {
336 kprintf("PCI: (%d,%d,%d) VGA (%04x:%04x)\n",
337 bus, device, func, vendorId, deviceId);
338 } else if ((baseClass == PCI_CLASS_BUS) && (subClass == PCI_SCLASS_BUS_SMBUS)) {
339 kprintf("PCI: (%d,%d,%d) SMBUS (%04x:%04x)\n",
340 bus, device, func, vendorId, deviceId);
341 } else {
342 kprintf("PCI: (%d,%d,%d) Unsupported (%04x:%04x %02x:%02x)\n",
343 bus, device, func, vendorId, deviceId, baseClass, subClass);
344 }
345}
346
347static void
349{
350 uint8_t device;
351 uint8_t headerType;
352 uint16_t vendorId;
353
354 for (device = 0; device < 32; device++) {
355 vendorId = PCIGetVendorID(bus, device, 0);
356 if (vendorId == 0xFFFF)
357 return;
358
359 DebugPCICheckFunction(bus, device, 0);
360
361 headerType = PCIGetHeaderType(bus, device, 0);
362 if ((headerType & 0x80) != 0) {
363 uint8_t func;
364 for (func = 0; func < 8; func++) {
365 if (PCIGetVendorID(bus, device, func) != 0xFFFF) {
366 DebugPCICheckFunction(bus, device, func);
367 }
368 }
369 }
370 }
371}
372
373void
374Debug_PCIList(int argc, const char *argv[])
375{
376 uint8_t headerType = PCIGetHeaderType(0, 0, 0);
377
378 if ((headerType & 0x80) == 0) {
380 } else {
381 uint8_t busNo;
382
383 for (busNo = 0; busNo < 8; busNo++) {
384 if (PCIGetVendorID(0, 0, busNo) != 0xFFFF)
385 break;
386 DebugPCIScanBus(busNo);
387 }
388 }
389}
390
391REGISTER_DBGCMD(pcilist, "PCI Device List", Debug_PCIList);
392
393void
394Debug_PCIDump(int argc, const char *argv[])
395{
396 uint32_t bus, device, func;
397 uint32_t bar;
398
399 if (argc != 4) {
400 kprintf("Requires 3 arguments!\n");
401 return;
402 }
403
404 bus = Debug_StrToInt(argv[1]);
405 device = Debug_StrToInt(argv[2]);
406 func = Debug_StrToInt(argv[3]);
407
408 kprintf("Vendor ID: %04x\n", PCIGetVendorID(bus, device, func));
409 kprintf("Device ID: %04x\n", PCIGetDeviceID(bus, device, func));
410 kprintf("Class: %d\n", PCIGetBaseClass(bus, device, func));
411 kprintf("Subclass: %d\n", PCIGetSubClass(bus, device, func));
412 kprintf("Header Type: %d\n", PCIGetHeaderType(bus, device, func));
413
414 for (bar = 0; bar < PCI_MAX_BARS; bar++)
415 {
416 uint32_t barReg = PCI_OFFSET_BARFIRST + 4 * bar;
417
418 kprintf("BAR%d: %016llx\n", bar, PCICfgRead32(bus, device, func, barReg));
419 }
420}
421
422REGISTER_DBGCMD(pcidump, "PCI Device Dump", Debug_PCIDump);
423
uint32_t PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
Definition: pci.c:43
uint8_t PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
Definition: pci.c:21
void PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint8_t data)
Definition: pci.c:55
void PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint32_t data)
Definition: pci.c:77
void PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint16_t data)
Definition: pci.c:66
uint16_t PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
Definition: pci.c:31
void PCI_Init()
Definition: pci.c:27
void PCI_CfgWrite32(PCIDevice *dev, uint32_t reg, uint32_t data)
Definition: pci.c:95
uint8_t PCI_GetHeaderType(PCIDevice *dev)
Definition: pci.c:125
static void PCIScan()
Definition: pci.c:226
static void PCIScanDevice(uint32_t bus, uint32_t device)
Definition: pci.c:188
void PCI_CfgWrite8(PCIDevice *dev, uint32_t reg, uint8_t data)
Definition: pci.c:83
static void PCICheckFunction(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:136
void Debug_PCIList(int argc, const char *argv[])
Definition: pci.c:374
void Debug_PCIDump(int argc, const char *argv[])
Definition: pci.c:394
uint16_t PCI_GetVendorID(PCIDevice *dev)
Definition: pci.c:107
uint8_t PCI_GetBaseClass(PCIDevice *dev)
Definition: pci.c:113
static void DebugPCICheckFunction(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:299
uint16_t PCI_GetDeviceID(PCIDevice *dev)
Definition: pci.c:101
uint16_t PCIGetVendorID(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:41
void PCI_CfgWrite16(PCIDevice *dev, uint32_t reg, uint16_t data)
Definition: pci.c:89
void AHCI_Init(uint32_t bus, uint32_t device, uint32_t func)
Definition: ahci.c:183
static void DebugPCIScanBus(uint8_t bus)
Definition: pci.c:348
uint8_t PCIGetSubClass(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:53
void E1000_Init(uint32_t bus, uint32_t device, uint32_t func)
Definition: e1000.c:168
uint32_t PCI_CfgRead32(PCIDevice *dev, uint32_t reg)
Definition: pci.c:77
uint16_t PCIGetDeviceID(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:35
void PCI_Configure(PCIDevice *dev)
Definition: pci.c:249
uint8_t PCIGetHeaderType(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:59
uint8_t PCIGetBaseClass(uint32_t bus, uint32_t device, uint32_t func)
Definition: pci.c:47
uint16_t PCI_CfgRead16(PCIDevice *dev, uint32_t reg)
Definition: pci.c:71
uint8_t PCI_CfgRead8(PCIDevice *dev, uint32_t reg)
Definition: pci.c:65
uint8_t PCI_GetSubClass(PCIDevice *dev)
Definition: pci.c:119
static void PCIScanBus(uint8_t bus)
Definition: pci.c:211
#define ASSERT(_x)
Definition: kassert.h:8
int kprintf(const char *fmt,...)
Definition: printf.c:210
uint64_t Debug_StrToInt(const char *s)
Definition: debug.c:124
#define REGISTER_DBGCMD(_NAME, _DESC, _FUNC)
Definition: kdebug.h:11
uint32_t size
Definition: multiboot.h:0
#define PCI_SCLASS_BUS_SMBUS
Definition: pci.h:42
#define PCI_SCLASS_BRIDGE_PCI
Definition: pci.h:37
#define PCI_COMMAND_MEMENABLE
Definition: pci.h:21
#define PCI_OFFSET_BARFIRST
Definition: pci.h:15
#define PCI_SCLASS_BRIDGE_ISA
Definition: pci.h:36
#define PCI_MAX_BARS
Definition: pci.h:24
#define PCI_OFFSET_IRQLINE
Definition: pci.h:18
#define PCI_OFFSET_VENDORID
Definition: pci.h:2
#define PCI_CLASS_NETWORK
Definition: pci.h:27
#define PCIBAR_TYPE_NULL
Definition: pci.h:44
uint8_t irq
Definition: pci.h:64
uint8_t slot
Definition: pci.h:61
#define PCI_CLASS_BRIDGE
Definition: pci.h:29
#define PCI_CLASS_BUS
Definition: pci.h:30
#define PCIBAR_TYPE_IO
Definition: pci.h:45
#define PCI_COMMAND_BUSMASTER
Definition: pci.h:22
#define PCI_OFFSET_SUBCLASS
Definition: pci.h:8
#define PCI_SCLASS_BRIDGE_MISC
Definition: pci.h:38
#define PCI_OFFSET_CLASS
Definition: pci.h:9
#define PCI_SCLASS_STORAGE_SATA
Definition: pci.h:33
PCIBAR bars[PCI_MAX_BARS]
Definition: pci.h:66
uint8_t func
Definition: pci.h:62
#define PCI_CLASS_STORAGE
Definition: pci.h:26
#define PCI_OFFSET_COMMAND
Definition: pci.h:4
uint32_t base
Definition: pci.h:50
#define PCIBAR_TYPE_MEM
Definition: pci.h:46
#define PCI_SCLASS_STORAGE_IDE
Definition: pci.h:32
uint32_t size
Definition: pci.h:51
#define PCI_OFFSET_HEADERTYPE
Definition: pci.h:12
#define PCI_COMMAND_IOENABLE
Definition: pci.h:20
#define PCI_CLASS_GRAPHICS
Definition: pci.h:28
uint8_t bus
Definition: pci.h:60
uint32_t type
Definition: pci.h:52
#define PCI_OFFSET_DEVICEID
Definition: pci.h:3
#define PCI_SCLASS_BRIDGE_HOST
Definition: pci.h:35
Definition: pci.h:56
static uint16_t base
Definition: sercons.c:37
unsigned short uint16_t
Definition: types.h:11
unsigned int uint32_t
Definition: types.h:12
unsigned char uint8_t
Definition: types.h:10