1 | /*␊ |
2 | *␊ |
3 | * Copyright 2008 by Islam M. Ahmed Zaid. All rights reserved.␊ |
4 | *␊ |
5 | */␊ |
6 | ␊ |
7 | #include "libsaio.h"␊ |
8 | #include "bootstruct.h"␊ |
9 | #include "pci.h"␊ |
10 | #include "modules.h"␊ |
11 | #include "platform.h"␊ |
12 | ␊ |
13 | #ifndef DEBUG_PCI␊ |
14 | #define DEBUG_PCI 0␊ |
15 | #endif␊ |
16 | ␊ |
17 | #if DEBUG_PCI␊ |
18 | #define DBG(x...)␉␉printf(x)␊ |
19 | #else␊ |
20 | #define DBG(x...)␊ |
21 | #endif␊ |
22 | ␊ |
23 | static void scan_pci_bus(pci_dt_t *start, uint8_t bus);␊ |
24 | static void enable_pci_devs(void);␊ |
25 | ␊ |
26 | uint8_t pci_config_read8(uint32_t pci_addr, uint8_t reg)␊ |
27 | {␊ |
28 | ␉pci_addr |= reg & ~3;␊ |
29 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
30 | ␉return inb(PCI_DATA_REG + (reg & 3));␊ |
31 | }␊ |
32 | ␊ |
33 | uint16_t pci_config_read16(uint32_t pci_addr, uint8_t reg)␊ |
34 | {␊ |
35 | ␉pci_addr |= reg & ~3;␊ |
36 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
37 | ␉return inw(PCI_DATA_REG + (reg & 2));␊ |
38 | }␊ |
39 | ␊ |
40 | uint32_t pci_config_read32(uint32_t pci_addr, uint8_t reg)␊ |
41 | {␊ |
42 | ␉pci_addr |= reg & ~3;␊ |
43 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
44 | ␉return inl(PCI_DATA_REG);␊ |
45 | }␊ |
46 | ␊ |
47 | void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data)␊ |
48 | {␊ |
49 | ␉pci_addr |= reg & ~3;␊ |
50 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
51 | ␉outb(PCI_DATA_REG + (reg & 3), data);␊ |
52 | }␊ |
53 | ␊ |
54 | void pci_config_write16(uint32_t pci_addr, uint8_t reg, uint16_t data)␊ |
55 | {␊ |
56 | ␉pci_addr |= reg & ~3;␊ |
57 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
58 | ␉outw(PCI_DATA_REG + (reg & 2), data);␊ |
59 | }␊ |
60 | ␊ |
61 | void pci_config_write32(uint32_t pci_addr, uint8_t reg, uint32_t data)␊ |
62 | {␊ |
63 | ␉pci_addr |= reg & ~3;␊ |
64 | ␉outl(PCI_ADDR_REG, pci_addr);␊ |
65 | ␉outl(PCI_DATA_REG, data);␊ |
66 | }␊ |
67 | ␊ |
68 | static void scan_pci_bus(pci_dt_t *start, uint8_t bus)␊ |
69 | {␊ |
70 | ␉pci_dt_t␉*new;␊ |
71 | ␉pci_dt_t␉**current = &start->children;␊ |
72 | ␉uint32_t␉id;␊ |
73 | ␉uint32_t␉pci_addr;␊ |
74 | ␉uint8_t␉␉dev;␊ |
75 | ␉uint8_t␉␉func;␊ |
76 | ␉uint8_t␉␉secondary_bus;␊ |
77 | ␉uint8_t␉␉header_type;␊ |
78 | ␉␊ |
79 | ␉for (dev = 0; dev < 32; dev++)␊ |
80 | ␉{␊ |
81 | ␉␉for (func = 0; func < 8; func++)␊ |
82 | ␉␉{␊ |
83 | ␉␉␉pci_addr = PCIADDR(bus, dev, func);␊ |
84 | ␉␉␉id = pci_config_read32(pci_addr, PCI_VENDOR_ID);␊ |
85 | ␉␉␉if (!id || id == 0xffffffff)␊ |
86 | ␉␉␉{␊ |
87 | ␉␉␉␉continue;␊ |
88 | ␉␉␉}␊ |
89 | ␉␉␉new = (pci_dt_t*)malloc(sizeof(pci_dt_t));␊ |
90 | if (!new) {␊ |
91 | continue;␊ |
92 | }␊ |
93 | ␉␉␉bzero(new, sizeof(pci_dt_t));␊ |
94 | ␉␉␉new->dev.addr␉= pci_addr;␊ |
95 | ␉␉␉new->vendor_id␉= id & 0xffff;␊ |
96 | ␉␉␉new->device_id␉= (id >> 16) & 0xffff;␊ |
97 | ␉␉␉new->subsys_id.subsys_id␉= pci_config_read32(pci_addr, PCI_SUBSYSTEM_VENDOR_ID);␊ |
98 | ␉␉␉new->class_id␉= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);␊ |
99 | ␉␉␉new->parent␉= start;␊ |
100 | ␉␉␉␊ |
101 | ␉␉␉header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);␊ |
102 | ␉␉␉switch (header_type & 0x7f)␊ |
103 | ␉␉␉{␊ |
104 | ␉␉␉␉case PCI_HEADER_TYPE_BRIDGE:␊ |
105 | ␉␉␉␉case PCI_HEADER_TYPE_CARDBUS:␊ |
106 | ␉␉␉␉␉secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);␊ |
107 | ␉␉␉␉␉if (secondary_bus != 0)␊ |
108 | ␉␉␉␉␉{␊ |
109 | ␉␉␉␉␉␉scan_pci_bus(new, secondary_bus);␊ |
110 | ␉␉␉␉␉}␊ |
111 | ␉␉␉␉␉break;␊ |
112 | ␉␉␉␉default:␊ |
113 | ␉␉␉␉␉break;␊ |
114 | ␉␉␉}␊ |
115 | ␉␉␉*current = new;␊ |
116 | ␉␉␉current = &new->next;␊ |
117 | ␉␉␉␊ |
118 | ␉␉␉if ((func == 0) && ((header_type & 0x80) == 0))␊ |
119 | ␉␉␉{␊ |
120 | ␉␉␉␉break;␊ |
121 | ␉␉␉}␊ |
122 | ␉␉}␊ |
123 | ␉}␊ |
124 | }␊ |
125 | ␊ |
126 | static void enable_pci_devs(void)␊ |
127 | {␊ |
128 | ␉uint16_t id;␊ |
129 | ␉uint32_t rcba, *fd;␊ |
130 | ␉␊ |
131 | ␉id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00);␊ |
132 | ␉/* make sure we're on Intel chipset */␊ |
133 | ␉if (id != 0x8086)␊ |
134 | ␉␉return;␊ |
135 | ␉rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1;␊ |
136 | ␉fd = (uint32_t *)(rcba + 0x3418);␊ |
137 | ␉/* set SMBus Disable (SD) to 0 */␊ |
138 | ␉*fd &= ~0x8;␊ |
139 | ␉/* and all devices? */␊ |
140 | ␉//*fd = 0x1;␊ |
141 | }␊ |
142 | ␊ |
143 | ␊ |
144 | void build_pci_dt(void)␊ |
145 | {␊ |
146 | pci_dt_t␉*root_pci_dev;␊ |
147 | ␊ |
148 | ␉root_pci_dev = malloc(sizeof(pci_dt_t)); ␊ |
149 | ␊ |
150 | if (!root_pci_dev)␊ |
151 | {␊ |
152 | stop("Couldn't allocate memory for the pci root device\n");␊ |
153 | return ;␊ |
154 | }␊ |
155 | set_env(envPCIRootDev,(uint32_t)root_pci_dev);␊ |
156 | ␊ |
157 | ␉bzero(root_pci_dev, sizeof(pci_dt_t));␊ |
158 | ␉enable_pci_devs();␊ |
159 | ␉scan_pci_bus(root_pci_dev, 0);␊ |
160 | #if DEBUG_PCI␊ |
161 | #ifndef OPTION_ROM␊ |
162 | ␉dump_pci_dt(root_pci_dev->children);␊ |
163 | ␉pause();␊ |
164 | #endif␊ |
165 | #endif␊ |
166 | }␊ |
167 | ␊ |
168 | static void setup_pci_devs(pci_dt_t *current)␊ |
169 | { ␊ |
170 | ␉␊ |
171 | ␉while (current)␊ |
172 | ␉{␊ |
173 | ␉␉execute_hook("PCIDevice", (void*)current, NULL, NULL, NULL, NULL, NULL);␊ |
174 | ␉␉␊ |
175 | ␉␉setup_pci_devs(current->children);␊ |
176 | ␉␉current = current->next;␊ |
177 | ␉}␊ |
178 | }␊ |
179 | ␊ |
180 | void setup_root_pci_devs(void)␊ |
181 | {␊ |
182 | pci_dt_t *root_pci_dev = (pci_dt_t *)(uint32_t)get_env(envPCIRootDev);␊ |
183 | ␊ |
184 | if (!root_pci_dev)␊ |
185 | {␊ |
186 | stop("No PCI root device\n");␊ |
187 | return ;␊ |
188 | }␊ |
189 | ␉␊ |
190 | ␉setup_pci_devs(root_pci_dev);␊ |
191 | }␊ |
192 | ␊ |
193 | #ifndef OPTION_ROM␊ |
194 | void dump_pci_dt(pci_dt_t *pci_dt)␊ |
195 | {␊ |
196 | ␉pci_dt_t␉*current;␊ |
197 | ␉␊ |
198 | ␉current = pci_dt;␊ |
199 | ␉while (current) ␊ |
200 | ␉{␊ |
201 | ␉␉printf("%02x:%02x.%x [%04x] [%04x:%04x] \n", ␊ |
202 | ␉␉␉ current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func, ␊ |
203 | ␉␉␉ current->class_id, current->vendor_id, current->device_id);␊ |
204 | ␉␉dump_pci_dt(current->children);␊ |
205 | ␉␉current = current->next;␊ |
206 | ␉}␊ |
207 | }␊ |
208 | #endif␊ |
209 | ␊ |
210 | static int rootuid = 10; //value means function wasnt ran yet␊ |
211 | ␊ |
212 | /*␊ |
213 | * getPciRootUID: Copyright 2009 netkas␊ |
214 | */␊ |
215 | int getPciRootUID(void)␊ |
216 | {␊ |
217 | ␉const char *val;␊ |
218 | ␉int len;␊ |
219 | ␉␊ |
220 | ␉if (rootuid < 10) return rootuid;␊ |
221 | ␉rootuid = 0;␉/* default uid = 0 */␊ |
222 | ␉␊ |
223 | ␉if (getValueForKey(kPCIRootUID, &val, &len, DEFAULT_BOOT_CONFIG))␊ |
224 | ␉{␊ |
225 | ␉␉if (isdigit(val[0])) rootuid = val[0] - '0';␊ |
226 | ␉␉␊ |
227 | ␉␉if ( (rootuid >= 0) && (rootuid < 10) ) ␊ |
228 | ␉␉␉goto out;␊ |
229 | ␉␉else␊ |
230 | ␉␉␉rootuid = 0;␊ |
231 | ␉}␉␊ |
232 | ␉␊ |
233 | ␉/* PCEFI compatibility */␊ |
234 | ␉if (getValueForKey("-pci0", &val, &len, DEFAULT_BOOT_CONFIG))␊ |
235 | ␉{␊ |
236 | ␉␉rootuid = 0;␊ |
237 | ␉}␊ |
238 | ␉else if (getValueForKey("-pci1", &val, &len, DEFAULT_BOOT_CONFIG))␊ |
239 | ␉{␊ |
240 | ␉␉rootuid = 1;␊ |
241 | ␉}␊ |
242 | out:␊ |
243 | ␉verbose("Using PCI-Root-UID value: %d\n", rootuid);␊ |
244 | ␉return rootuid;␊ |
245 | } |