Fix error in pci_find_class().
[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
12 #define MAX_BUS 1
13
14 void pci_config_writel(PCIDevice d, u32 addr, u32 val)
15 {
16     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
17          , PORT_PCI_CMD);
18     outl(val, PORT_PCI_DATA);
19 }
20
21 void pci_config_writew(PCIDevice d, u32 addr, u16 val)
22 {
23     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
24          , PORT_PCI_CMD);
25     outw(val, PORT_PCI_DATA + (addr & 2));
26 }
27
28 void pci_config_writeb(PCIDevice d, u32 addr, u8 val)
29 {
30     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
31          , PORT_PCI_CMD);
32     outb(val, PORT_PCI_DATA + (addr & 3));
33 }
34
35 u32 pci_config_readl(PCIDevice d, u32 addr)
36 {
37     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
38          , PORT_PCI_CMD);
39     return inl(PORT_PCI_DATA);
40 }
41
42 u16 pci_config_readw(PCIDevice d, u32 addr)
43 {
44     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
45          , PORT_PCI_CMD);
46     return inw(PORT_PCI_DATA + (addr & 2));
47 }
48
49 u8 pci_config_readb(PCIDevice d, u32 addr)
50 {
51     outl(0x80000000 | (d.bus << 16) | (d.devfn << 8) | (addr & 0xfc)
52          , PORT_PCI_CMD);
53     return inb(PORT_PCI_DATA + (addr & 3));
54 }
55
56 int
57 pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev)
58 {
59     int devfn, bus;
60     u32 id = (devid << 16) | vendid;
61     for (bus=0; bus < MAX_BUS; bus++) {
62         for (devfn=0; devfn<0x100; devfn++) {
63             PCIDevice d = pci_bd(bus, devfn);
64             u32 v = pci_config_readl(d, 0x00);
65             if (v != id)
66                 continue;
67             if (index) {
68                 index--;
69                 continue;
70             }
71             // Found it.
72             *dev = d;
73             return 0;
74         }
75     }
76     return -1;
77 }
78
79 int
80 pci_find_class(u32 classid, int index, PCIDevice *dev)
81 {
82     int devfn, bus;
83     for (bus=0; bus < MAX_BUS; 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) != classid)
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 }