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
9 static void PCIScan();
10
11 // Platform functions
12 uint8_t PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
13 uint16_t PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
14 uint32_t PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
15 void PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func,
16 uint32_t reg, uint8_t data);
17 void PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func,
18 uint32_t reg, uint16_t data);
19 void PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func,
20 uint32_t reg, uint32_t data);
21
22 // Supported Devices
23 void AHCI_Init(uint32_t bus, uint32_t device, uint32_t func);
24 void E1000_Init(uint32_t bus, uint32_t device, uint32_t func);
25
26 void
PCI_Init()27 PCI_Init()
28 {
29 kprintf("PCI: Initializing ...\n");
30 PCIScan();
31 kprintf("PCI: Initialization Done!\n");
32 }
33
34 uint16_t
PCIGetDeviceID(uint32_t bus,uint32_t device,uint32_t func)35 PCIGetDeviceID(uint32_t bus, uint32_t device, uint32_t func)
36 {
37 return PCICfgRead16(bus, device, func, PCI_OFFSET_DEVICEID);
38 }
39
40 uint16_t
PCIGetVendorID(uint32_t bus,uint32_t device,uint32_t func)41 PCIGetVendorID(uint32_t bus, uint32_t device, uint32_t func)
42 {
43 return PCICfgRead16(bus, device, func, PCI_OFFSET_VENDORID);
44 }
45
46 uint8_t
PCIGetBaseClass(uint32_t bus,uint32_t device,uint32_t func)47 PCIGetBaseClass(uint32_t bus, uint32_t device, uint32_t func)
48 {
49 return PCICfgRead8(bus, device, func, PCI_OFFSET_CLASS);
50 }
51
52 uint8_t
PCIGetSubClass(uint32_t bus,uint32_t device,uint32_t func)53 PCIGetSubClass(uint32_t bus, uint32_t device, uint32_t func)
54 {
55 return PCICfgRead8(bus, device, func, PCI_OFFSET_SUBCLASS);
56 }
57
58 uint8_t
PCIGetHeaderType(uint32_t bus,uint32_t device,uint32_t func)59 PCIGetHeaderType(uint32_t bus, uint32_t device, uint32_t func)
60 {
61 return PCICfgRead8(bus, device, func, PCI_OFFSET_HEADERTYPE);
62 }
63
64 uint8_t
PCI_CfgRead8(PCIDevice * dev,uint32_t reg)65 PCI_CfgRead8(PCIDevice *dev, uint32_t reg)
66 {
67 return PCICfgRead8(dev->bus, dev->slot, dev->func, reg);
68 }
69
70 uint16_t
PCI_CfgRead16(PCIDevice * dev,uint32_t reg)71 PCI_CfgRead16(PCIDevice *dev, uint32_t reg)
72 {
73 return PCICfgRead16(dev->bus, dev->slot, dev->func, reg);
74 }
75
76 uint32_t
PCI_CfgRead32(PCIDevice * dev,uint32_t reg)77 PCI_CfgRead32(PCIDevice *dev, uint32_t reg)
78 {
79 return PCICfgRead32(dev->bus, dev->slot, dev->func, reg);
80 }
81
82 void
PCI_CfgWrite8(PCIDevice * dev,uint32_t reg,uint8_t data)83 PCI_CfgWrite8(PCIDevice *dev, uint32_t reg, uint8_t data)
84 {
85 return PCICfgWrite8(dev->bus, dev->slot, dev->func, reg, data);
86 }
87
88 void
PCI_CfgWrite16(PCIDevice * dev,uint32_t reg,uint16_t data)89 PCI_CfgWrite16(PCIDevice *dev, uint32_t reg, uint16_t data)
90 {
91 return PCICfgWrite16(dev->bus, dev->slot, dev->func, reg, data);
92 }
93
94 void
PCI_CfgWrite32(PCIDevice * dev,uint32_t reg,uint32_t data)95 PCI_CfgWrite32(PCIDevice *dev, uint32_t reg, uint32_t data)
96 {
97 return PCICfgWrite32(dev->bus, dev->slot, dev->func, reg, data);
98 }
99
100 uint16_t
PCI_GetDeviceID(PCIDevice * dev)101 PCI_GetDeviceID(PCIDevice *dev)
102 {
103 return PCI_CfgRead16(dev, PCI_OFFSET_DEVICEID);
104 }
105
106 uint16_t
PCI_GetVendorID(PCIDevice * dev)107 PCI_GetVendorID(PCIDevice *dev)
108 {
109 return PCI_CfgRead16(dev, PCI_OFFSET_VENDORID);
110 }
111
112 uint8_t
PCI_GetBaseClass(PCIDevice * dev)113 PCI_GetBaseClass(PCIDevice *dev)
114 {
115 return PCI_CfgRead8(dev, PCI_OFFSET_CLASS);
116 }
117
118 uint8_t
PCI_GetSubClass(PCIDevice * dev)119 PCI_GetSubClass(PCIDevice *dev)
120 {
121 return PCI_CfgRead8(dev, PCI_OFFSET_SUBCLASS);
122 }
123
124 uint8_t
PCI_GetHeaderType(PCIDevice * dev)125 PCI_GetHeaderType(PCIDevice *dev)
126 {
127 return PCI_CfgRead8(dev, PCI_OFFSET_HEADERTYPE);
128 }
129
130 /*
131 * PCICheckFunction --
132 *
133 * Identify device type and initialize known devices.
134 */
135 static void
PCICheckFunction(uint32_t bus,uint32_t device,uint32_t func)136 PCICheckFunction(uint32_t bus, uint32_t device, uint32_t func)
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
187 static void
PCIScanDevice(uint32_t bus,uint32_t device)188 PCIScanDevice(uint32_t bus, uint32_t device)
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
210 static void
PCIScanBus(uint8_t bus)211 PCIScanBus(uint8_t bus)
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 */
225 static void
PCIScan()226 PCIScan()
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 */
248 void
PCI_Configure(PCIDevice * dev)249 PCI_Configure(PCIDevice *dev)
250 {
251 int bar;
252
253 dev->irq = PCI_CfgRead8(dev, PCI_OFFSET_IRQLINE);
254
255 PCI_CfgWrite16(dev, PCI_OFFSET_COMMAND,
256 PCI_COMMAND_IOENABLE | PCI_COMMAND_MEMENABLE | PCI_COMMAND_BUSMASTER);
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;
268 uint32_t base, size;
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
298 static void
DebugPCICheckFunction(uint32_t bus,uint32_t device,uint32_t func)299 DebugPCICheckFunction(uint32_t bus, uint32_t device, uint32_t func)
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
347 static void
DebugPCIScanBus(uint8_t bus)348 DebugPCIScanBus(uint8_t bus)
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
373 void
Debug_PCIList(int argc,const char * argv[])374 Debug_PCIList(int argc, const char *argv[])
375 {
376 uint8_t headerType = PCIGetHeaderType(0, 0, 0);
377
378 if ((headerType & 0x80) == 0) {
379 DebugPCIScanBus(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
391 REGISTER_DBGCMD(pcilist, "PCI Device List", Debug_PCIList);
392
393 void
Debug_PCIDump(int argc,const char * argv[])394 Debug_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
422 REGISTER_DBGCMD(pcidump, "PCI Device Dump", Debug_PCIDump);
423
424