1 | #include <bsp.h> |
---|
2 | |
---|
3 | static const void *PciConfAddr = IO_TO_LOCAL(0x0cf8); |
---|
4 | static const void *PciConfData = IO_TO_LOCAL(0x0cfc); |
---|
5 | |
---|
6 | int pci_make_devsig(int bus, int device, int function) { |
---|
7 | return ((bus & 255) << 16) | ((device & 31) << 11) | |
---|
8 | ((function & 7) << 8) | 0x80000000; |
---|
9 | } |
---|
10 | |
---|
11 | int pci_conf_read8(int sig, int off) { |
---|
12 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
13 | synchronize_io(); |
---|
14 | return *(unsigned char *)(PciConfData + (off & 3)); |
---|
15 | } |
---|
16 | |
---|
17 | int pci_conf_read16(int sig, int off) { |
---|
18 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
19 | synchronize_io(); |
---|
20 | return ld_le16(PciConfData + (off & 3)); |
---|
21 | } |
---|
22 | |
---|
23 | int pci_conf_read32(int sig, int off) { |
---|
24 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
25 | synchronize_io(); |
---|
26 | return ld_le32(PciConfData); |
---|
27 | } |
---|
28 | |
---|
29 | void pci_conf_write8(int sig, int off, unsigned int data) { |
---|
30 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
31 | synchronize_io(); |
---|
32 | *(unsigned char *)(PciConfData + (off & 3)) = data; |
---|
33 | } |
---|
34 | |
---|
35 | void pci_conf_write16(int sig, int off, unsigned int data) { |
---|
36 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
37 | synchronize_io(); |
---|
38 | st_le16(PciConfData + (off & 3), data); |
---|
39 | } |
---|
40 | |
---|
41 | void pci_conf_write32(int sig, int off, unsigned int data) { |
---|
42 | st_le32(PciConfAddr, sig + (off & 252)); |
---|
43 | synchronize_io(); |
---|
44 | st_le32(PciConfData + (off & 3), data); |
---|
45 | } |
---|
46 | |
---|
47 | static int recursive_find(int bus, int devid_venid, int idx, int *count) { |
---|
48 | int devsig, dev, func, max_func, idreg, class, secondary_bus; |
---|
49 | char header_type; |
---|
50 | |
---|
51 | for (dev = 0; dev < 32; dev++) { |
---|
52 | devsig = pci_make_devsig(bus, dev, 0); |
---|
53 | header_type = pci_conf_read8(devsig, 0x0e); |
---|
54 | max_func = (header_type & 0x80) ? 8 : 1; /* multi-function device? */ |
---|
55 | for (func = 0; func < max_func; func++) { |
---|
56 | devsig = pci_make_devsig(bus, dev, func); |
---|
57 | idreg = pci_conf_read32(devsig, 0x00); |
---|
58 | if (idreg == 0xffffffff) { |
---|
59 | break; /* empty slot */ |
---|
60 | } |
---|
61 | if (idreg == devid_venid) { |
---|
62 | /* id's match - is it the right instance? */ |
---|
63 | if (*count == idx) { |
---|
64 | return devsig; |
---|
65 | } else { |
---|
66 | (*count)++; |
---|
67 | } |
---|
68 | } |
---|
69 | class = pci_conf_read32(devsig, 0x08) & 0xffff0000; |
---|
70 | if (class == 0x06040000) { /* pci-pci bridge? */ |
---|
71 | secondary_bus = pci_conf_read8(devsig, 0x19); |
---|
72 | devsig = recursive_find(secondary_bus, devid_venid, idx, count); |
---|
73 | if (devsig != PCI_NOT_FOUND) { |
---|
74 | return devsig; |
---|
75 | } |
---|
76 | } |
---|
77 | } |
---|
78 | } |
---|
79 | return PCI_NOT_FOUND; |
---|
80 | } |
---|
81 | |
---|
82 | int pci_find_by_devid(int vendorId, int devId, int idx) { |
---|
83 | int count = 0; |
---|
84 | int devid_venid = ((devId << 16) & 0xffff0000) | (vendorId & 0xffff); |
---|
85 | |
---|
86 | return recursive_find(0, devid_venid, idx, &count); |
---|
87 | } |
---|