]> Joshua Wise's Git repositories - netwatch.git/blob - pci/pci.c
actual license now
[netwatch.git] / pci / pci.c
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
14 int 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
82 static 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
109 void pci_bus_enum()
110 {
111         pci_probe(_enumfn, 0x0);
112 }
113
114 static 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
128 int pci_probe_driver(pci_driver_t *driver)
129 {
130         return pci_probe(_probefn, driver);
131 }
This page took 0.034361 seconds and 4 git commands to generate.