1f11ee3b978a71f409169c57dced1e8c1f08b6c0
[seabios.git] / src / pci.c
1 // PCI config space access functions.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU GPLv3 license.
7
8 #include "pci.h" // PCIDevice
9 #include "ioport.h" // outl
10 #include "util.h" // dprintf
11 #include "config.h" // CONFIG_*
12
13 void pci_config_writel(PCIDevice d, u32 addr, u32 val)
14 {
15     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
16          , PORT_PCI_CMD);
17     outl(val, PORT_PCI_DATA);
18 }
19
20 void pci_config_writew(PCIDevice d, u32 addr, u16 val)
21 {
22     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
23          , PORT_PCI_CMD);
24     outw(val, PORT_PCI_DATA + (addr & 2));
25 }
26
27 void pci_config_writeb(PCIDevice d, u32 addr, u8 val)
28 {
29     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
30          , PORT_PCI_CMD);
31     outb(val, PORT_PCI_DATA + (addr & 3));
32 }
33
34 u32 pci_config_readl(PCIDevice d, u32 addr)
35 {
36     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
37          , PORT_PCI_CMD);
38     return inl(PORT_PCI_DATA);
39 }
40
41 u16 pci_config_readw(PCIDevice d, u32 addr)
42 {
43     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
44          , PORT_PCI_CMD);
45     return inw(PORT_PCI_DATA + (addr & 2));
46 }
47
48 u8 pci_config_readb(PCIDevice d, u32 addr)
49 {
50     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
51          , PORT_PCI_CMD);
52     return inb(PORT_PCI_DATA + (addr & 3));
53 }
54
55 int
56 pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev)
57 {
58     int devfn, bus;
59     u32 id = (devid << 16) | vendid;
60     for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
61         for (devfn=0; devfn<0x100; devfn++) {
62             PCIDevice d = pci_bd(bus, devfn);
63             u32 v = pci_config_readl(d, PCI_VENDOR_ID);
64             if (v != id)
65                 continue;
66             if (index) {
67                 index--;
68                 continue;
69             }
70             // Found it.
71             *dev = d;
72             return 0;
73         }
74     }
75     return -1;
76 }
77
78 // Search for a device with the specified class id and prog-if.
79 int
80 pci_find_classprog(u32 classprog, int index, PCIDevice *dev)
81 {
82     int devfn, bus;
83     for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
84         for (devfn=0; devfn<0x100; devfn++) {
85             PCIDevice d = pci_bd(bus, devfn);
86             u32 v = pci_config_readl(d, 0x08);
87             if ((v>>8) != classprog)
88                 continue;
89             if (index) {
90                 index--;
91                 continue;
92             }
93             // Found it.
94             *dev = d;
95             return 0;
96         }
97     }
98     return -1;
99 }
100
101 // Search for a device with the specified class id.
102 int
103 pci_find_class(u16 classid, int index, PCIDevice *dev)
104 {
105     int devfn, bus;
106     for (bus=0; bus < CONFIG_PCI_BUS_COUNT; bus++) {
107         for (devfn=0; devfn<0x100; devfn++) {
108             PCIDevice d = pci_bd(bus, devfn);
109             u16 v = pci_config_readw(d, PCI_CLASS_DEVICE);
110             if (v != classid)
111                 continue;
112             if (index) {
113                 index--;
114                 continue;
115             }
116             // Found it.
117             *dev = d;
118             return 0;
119         }
120     }
121     return -1;
122 }