]> Joshua Wise's Git repositories - netwatch.git/blame_incremental - pci/pci.c
actual license now
[netwatch.git] / pci / pci.c
... / ...
CommitLineData
1/* pci.c
2 * General-purpose PCI probe routines
3 * NetWatch system management mode administration console
4 *
5 * Copyright (c) 2008 Jacob Potter and Joshua Wise. All rights reserved.
6 * This program is free software; you can redistribute and/or modify it under
7 * the terms found in the file LICENSE in the root of this source tree.
8 *
9 */
10
11#include <pci.h>
12#include <output.h>
13
14int pci_probe(pci_probe_fn_t probe, void *data)
15{
16 int devsfound = 0;
17 pci_dev_t pdev;
18 unsigned int bus;
19 unsigned int dev;
20 unsigned int fn;
21
22 for (bus = 0; bus < 0x100; bus++)
23 for (dev = 0; dev < 0x20; dev++)
24 {
25 if (pci_read32(bus, dev, 0, 0) == 0xFFFFFFFF)
26 continue;
27 for (fn = 0; fn < 8; fn++)
28 {
29 int bar;
30
31 if (pci_read32(bus, dev, fn, 0) == 0xFFFFFFFF)
32 continue;
33
34 if ((fn != 0) && !(pci_read8(bus, dev, 0, 0x0E) & 0x80))
35 continue;
36
37 pdev.bus = bus;
38 pdev.dev = dev;
39 pdev.fn = fn;
40 pdev.vid = pci_read16(bus, dev, fn, 0);
41 pdev.did = pci_read16(bus, dev, fn, 2);
42
43 for (bar = 0; bar < 6; bar++)
44 {
45 unsigned long bardat = pci_read32(bus, dev, fn, 0x10 + bar*4);
46 if (bardat == 0)
47 {
48 pdev.bars[bar].type = PCI_BAR_NONE;
49 continue;
50 }
51 if (bardat & 1)
52 {
53 pdev.bars[bar].type = PCI_BAR_IO;
54 pdev.bars[bar].addr = bardat & ~0x3;
55 } else {
56 pdev.bars[bar].prefetchable = (bardat >> 3) & 1;
57 switch ((bardat >> 1) & 0x3)
58 {
59 case 0:
60 pdev.bars[bar].type = PCI_BAR_MEMORY32;
61 pdev.bars[bar].addr = bardat & ~0xF;
62 break;
63 case 2:
64 pdev.bars[bar].type = PCI_BAR_MEMORY64;
65 bar++;
66 pdev.bars[bar].type = PCI_BAR_NONE;
67 break;
68 default:
69 pdev.bars[bar].type = PCI_BAR_NONE;
70 continue;
71 }
72 }
73 }
74
75 devsfound += probe(&pdev, data);
76 }
77 }
78
79 return devsfound;
80}
81
82static int _enumfn(pci_dev_t *pdev, void *data)
83{
84 int bar;
85
86 outputf("Found device: %02x:%02x.%1x: %04X:%04X",
87 pdev->bus, pdev->dev, pdev->fn,
88 pdev->vid, pdev->did);
89 for (bar = 0; bar < 6; bar++)
90 {
91 switch (pdev->bars[bar].type)
92 {
93 case PCI_BAR_IO:
94 outputf(" BAR %d: I/O, Addr %04x", bar, pdev->bars[bar].addr);
95 break;
96 case PCI_BAR_MEMORY32:
97 outputf(" BAR %d: Mem32, Addr %04x", bar, pdev->bars[bar].addr);
98 break;
99 case PCI_BAR_MEMORY64:
100 outputf(" BAR %d: Mem64, Addr %04x", bar, pdev->bars[bar].addr);
101 break;
102 default:
103 break;
104 }
105 }
106 return 0;
107}
108
109void pci_bus_enum()
110{
111 pci_probe(_enumfn, 0x0);
112}
113
114static int _probefn(pci_dev_t *dev, void *d)
115{
116 pci_driver_t *driver = d;
117 int i;
118
119 for (i = 0; i < driver->id_count; i++)
120 if ((dev->vid == driver->ids[i].vid) && (dev->did == driver->ids[i].did))
121 {
122 outputf("Probing PCI device: %s", driver->ids[i].name ? driver->ids[i].name : driver->name);
123 return driver->probe(dev, d);
124 }
125 return 0;
126}
127
128int pci_probe_driver(pci_driver_t *driver)
129{
130 return pci_probe(_probefn, driver);
131}
This page took 0.026383 seconds and 4 git commands to generate.